Course Content
LangChain Mastery
7 sections · 109 lessons
What is a try-except block in LangChain applications?
What you need to know
Where exceptions come from
| Exception | Raised by | Meaning | Usual response |
|---|---|---|---|
openai.RateLimitError (429) | Provider SDK | Too many requests | Retry with backoff |
openai.APITimeoutError, APIConnectionError | Provider SDK | Network or slow response | Retry, then fall back |
openai.InternalServerError (5xx) | Provider SDK | Provider outage | Retry, then fall back to another provider |
openai.BadRequestError (400) | Provider SDK | Bad request, context too long | Fix the input; don't retry |
OutputParserException | langchain_core.exceptions | Model reply didn't match the format | Re-ask or repair once |
pydantic.ValidationError | Your schemas | Input or output failed validation | Reject or repair |
LangChain's provider packages (langchain-openai, langchain-anthropic) let the SDK's exceptions pass through, so you catch the provider's classes.
A targeted handler
1import logging2import openai3from langchain_core.exceptions import OutputParserException45log = logging.getLogger(__name__)67def answer(question: str) -> str:8 try:9 return chain.invoke({"question": question})10 except OutputParserException:11 log.warning("parse_failure")12 return repair_chain.invoke({"question": question}) # one repair attempt13 except openai.BadRequestError as e:14 log.error("bad_request", extra={"status": e.status_code})15 return "Your question is too long. Please shorten it."16 except openai.APIError:17 log.exception("provider_error")18 return "The assistant is busy. Please try again in a minute."Order matters: specific classes before general ones. openai.APIError is the parent of the rate-limit, timeout and status errors.
Declarative handling on runnables
1robust = chain.with_retry(2 retry_if_exception_type=(openai.RateLimitError, openai.APITimeoutError),3 stop_after_attempt=3,4).with_fallbacks([backup_chain])This keeps retry and fallback logic next to the chain, and each attempt shows up in traces. In agents built with create_agent, the same ideas come as middleware: ModelRetryMiddleware, ModelFallbackMiddleware, ToolRetryMiddleware.
A real-life example
A finance assistant calls a stock-price API tool and a model. Early code wrapped everything in except Exception: return "Something went wrong". During a market-open spike, the model provider returned 429s for 3 minutes; users saw "Something went wrong" and support tickets tripled. Logs had no detail, so nobody knew it was rate limiting.
The fix: with_retry on the model for 429s and timeouts (3 attempts, exponential backoff with jitter), a fallback to a second provider, and a narrow try/except at the API edge that logs the exception class and returns a specific message. The next spike caused a 1.5-second slowdown for some users instead of failures.
Follow-up questions to expect
- "Why not catch
Exception?" — It hides bugs (like aKeyErrorin your own code) behind a generic message and makes you retry things that will never succeed. - "Where do you put the
try?" — At the boundary where you can do something useful: the API handler or a tool wrapper — not around every line. - "What about async?" — The same exceptions are raised from
ainvoke; handle them the same way.