Output parsers: retry, fix, or fail loudly
LangChain hands you a small drawer of output parsers, and the dangerous part is that the handiest tool in it is the one to reach for last. This is the ladder I climb now, built on an invoice-extraction pipeline where that handy tool once cost a client real money.
the drawer, safest to scariest
At the bottom sits StrOutputParser: it pulls the text out and does nothing else. Boring, unbreakable, and the right default for anything that is not structured.
Above it, structured output (with_structured_output or a Pydantic parser) hands the model a schema and returns a validated object. This is where you want to live, because constraining the shape up front prevents more errors than any cleanup afterward.
Then the two clever ones. OutputFixingParser sends malformed output to a second model call that tries to repair it; RetryParser reruns with the original prompt plus the error. Both turn a parse failure into another model call, and both are seductive for one reason: they make a red test go green.
That is exactly the problem.
the ladder I actually climb
My rule has three rungs, and I try hard never to skip to the top:
- Constrain first. A tight schema and an explicit format instruction kill most parse failures before they happen.
- Retry once, with the error in context, and exactly once. A model that cannot produce valid output on the second try will not manage it on the fifth; it will only bill you.
- Then fail loudly. A failure that survives the retry goes to a dead-letter queue with the raw output attached, and a human looks at it. Resilient pipelines route their failures out rather than smoothing them over.
The rung I kept skipping was the third. I had the first two and a faith that fixing would mop up the rest.
the afternoon fixing rewrote a number
Here is what that faith bought me. One invoice out of a batch of maybe 500 arrived with a malformed total: the model emitted something the schema rejected. OutputFixingParser did precisely its job and called a second model to make the output valid. Valid, not correct. It produced a number that parsed cleanly and was wrong, a plausible figure matching no line on the actual invoice, and because it satisfied the schema, nothing downstream said a word.
That wrong number flowed into the client's reconciliation export and sat there for days before someone matched it against the paper original.
A parser that turns invalid output into valid output hides the problem behind a number that looks fine.
I pulled OutputFixingParser out of anything touching money that same week. It still lives in one suggestion feature where a silently-repaired guess is harmless, nowhere near a field that has to be right. A parse failure is the model and your schema telling you they disagree, not noise to smooth away, and on a financial document that disagreement is the most valuable signal you get. Validate loudly and guard the outputs, and let the failures reach a person. The convenient tool is fine right up until it is the thing deciding what a number should have been.