TL;DR
- The
OutputParserExceptionfires when a ReAct-style agent’s output matches both the action pattern (Action:/Action Input:) and the final-answer prefix (Final Answer:) in the same turn, soReActSingleInputOutputParsercannot tell whether to dispatch a tool call or end the run. handle_parsing_errors=Truecatches the exception and, by default, feeds back a fixed placeholder message (“Invalid or incomplete response”) as the next observation rather than the actual error text — pass a custom string or callable instead ofTrueto send back something more specific- The most reliable fix is architectural: move off
initialize_agent‘s legacy text-parsing ReAct agent onto a native tool-calling agent, where the turn boundary is enforced by the provider’s API instead of a regex over free text.
Error Symptom: OutputParserException in ReAct Agent Execution
In a GitHub issue report, a zero-shot ReAct agent built with initialize_agent and AgentType.ZERO_SHOT_REACT_DESCRIPTION raised langchain_core.exceptions.OutputParserException: Parsing LLM output produced both a final answer and a parse-able action while running against a self-hosted Meta-Llama-3-8B-Instruct model through a Hugging Face pipeline, with a Wikipedia search tool and a DuckDuckGo search tool attached.
The reporter’s code, quoted as posted in the issue:
runAgent = initialize_agent(
llm=hf,
tools=tools,
verbose=True,
agent_type=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
)
userInput = "Bitcoin"
output = runAgent.run(f'Write an academic abstract about {userInput}')
This is reproduced verbatim from the report — hf and tools are defined earlier in the reporter’s own script and not shown here. Note that initialize_agent‘s formal parameter for selecting an agent type is agent, not agent_type. However, when both agent and agent_path are None, initialize_agent defaults to AgentType.ZERO_SHOT_REACT_DESCRIPTION. Thus, passing agent_type is ignored as an extra keyword argument, but the resulting instance is still a zero-shot ReAct agent and reproduces the exact same error.
When the model over-generates — for example continuing past a tool call to also emit Final Answer: in the same response, or fabricating its own Observation: lines and looping through several invented steps — ReActSingleInputOutputParser.parse() finds both an action match and the final-answer prefix in the same text and raises the exception instead of guessing which one the model meant.
After first hitting this, the reporter tried passing handle_parsing_errors=True. Rather than resolving cleanly, the run continued generating further hallucinated Thought/Action/Action Input/Observation cycles on its own without reaching a stop state — handle_parsing_errors=True catches the exception and passes the error back into the scratchpad, but it does not prevent the model from continuing to over-generate. A later comment on the same issue suggested adding early_stopping_method="force":
runAgent = initialize_agent(
llm=hf,
tools=tools,
verbose=True,
early_stopping_method="force",
handle_parsing_errors=True,
agent_type=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
)
"force" is already AgentExecutor‘s default value for early_stopping_method. The early_stopping_method parameter is independent of handle_parsing_errors and controls how the agent terminates once max_iterations or max_execution_time is reached (e.g., when repeated parsing retries exhaust the iteration limit), not at the moment the parsing conflict happens.
Sources: OutputParserException: Parsing LLM output produced both a final answer and a parse-able action
Root Cause: Turn Ambiguity in ReActSingleInputOutputParser Protocols
LangChain’s text-based ReAct agent protocol relies on a strict turn-by-turn structure in which tool execution and agent termination are meant to be mutually exclusive:
- Action step: the model emits
Thought:,Action: <tool_name>, andAction Input: <input>, and the runtime is meant to stop there, dispatch anAgentAction, run the tool, and inject the result as the nextObservation:. - Termination step: the model emits
Thought:andFinal Answer: <response>, and the runtime returns anAgentFinishto end the loop.
ReActSingleInputOutputParser (and the legacy MRKL parser) decide which of these happened by testing the model’s raw text for two separate patterns: an action match (Action: ... / Action Input: ...) and the final-answer prefix defined by the FINAL_ANSWER_ACTION constant ("Final Answer:"). The exception fires whenever both patterns match in the same output, which happens in at least two distinct ways:
- The model hallucinates the rest of the trajectory. After an
Action/Action Inputpair, the model keeps generating instead of stopping — inventing its ownObservation:text for a tool it never actually called, then continuing through furtherThought/Actioncycles until it eventually appends aFinal Answer:as well. - The model appends a final answer directly, with no fabricated observation in between. The model emits
Action:/Action Input:and then, in the same continuous response, immediately addsThought: I now know the final answerandFinal Answer:— without ever generating anObservation:line at all.
The distinction matters for choosing a fix: anything that stops generation at the Observation: boundary only intercepts case 1, because case 2 never produces that string in the first place. In both cases, because the runtime cannot tell from the text alone whether to dispatch an AgentAction or return an AgentFinish, ReActSingleInputOutputParser aborts and raises langchain_core.exceptions.OutputParserException using the string constant FINAL_ANSWER_AND_PARSABLE_ACTION_ERROR_MESSAGE.
Sources: langchain.schema.output_parser.OutputParserException · Issue #8226 · langchain-ai/langchain · GitHub, vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQGQ6Yvdmo…, エラー Parsing LLM output produced both a final answer and a parse-able action #LangChain – Qiita, FINAL_ANSWER_AND_PARSABLE_ACTION_ERROR_MESSAGE, Observation: Invalid or incomplete response using HF TGI · Issue #9381 · langchain-ai/langchain · GitHub
How to Fix It: From Quick Patch to Eliminating the Error Class
There are three points at which you can intervene, from patching around the crash to removing the ambiguity altogether.
1. Catch the exception with handle_parsing_errors. Passing handle_parsing_errors=True to initialize_agent/AgentExecutor stops OutputParserException from crashing the run by catching the exception and returning the error text (or a fallback like “Invalid or incomplete response”) back as an observation so the model can retry. Passing a custom string (e.g. handle_parsing_errors="<custom message>") or a callable lets you control the instructional prompt or dynamically sanitize the output. On its own this only manages the failure at runtime — it does not prevent the model from over-generating again on a later turn. If the model continually repeats parsing errors until hitting max_iterations or max_execution_time, early_stopping_method determines how the agent handles termination at that limit.
2. Verify and configure stop sequences for the Observation: boundary. Zero-shot ReAct agents in LangChain generally pass stop sequences such as ["\nObservation:", "\n\tObservation:"] to LLM invocations to halt generation immediately after an action is emitted. However, local model wrappers (such as Hugging Face pipeline wrappers) or certain model setups may fail to apply or honor these stop sequences properly. Verifying that stop arguments are actually respected by your LLM wrapper prevents case 1 — the model hallucinating its own observations and looping through further steps. Note that stop sequences do not prevent case 2, where the model appends Final Answer: directly after Action Input: without ever generating an Observation: token.
3. Move to a native tool-calling agent. ReActSingleInputOutputParser and other text-based parsers exist only because the ReAct protocol encodes actions and answers as plain text that has to be pattern-matched after the fact. Where the underlying model supports tool calling, building the agent with create_tool_calling_agent (or an equivalent structured-output agent) instead of initialize_agent‘s ZERO_SHOT_REACT_DESCRIPTION moves argument parsing and turn boundaries into the API itself, so there is no free-text Action:/Final Answer: pattern left to collide. This isn’t guaranteed for every model, though — a self-hosted model served through a Hugging Face pipeline, like the Meta-Llama-3-8B-Instruct example above, may not expose tool calling the way a hosted provider API does. It is also worth knowing that initialize_agent/AgentExecutor is LangChain’s older agent interface; current LangChain documentation points toward create_agent/LangGraph-based agents as the actively maintained path going forward.
Sources: langchain.schema.output_parser.OutputParserException · Issue #8226 · langchain-ai/langchain · GitHub, FINAL_ANSWER_AND_PARSABLE_ACTION_ERROR_MESSAGE
Closing thoughts
This parsing error illustrates the limitations of relying on regex-based text parsing for agent control flow when underlying LLMs generate past expected turn boundaries. While parameters like handle_parsing_errors handle parser exceptions at runtime by passing feedback back to the scratchpad, and early_stopping_method dictates how the run concludes when iteration limits are reached, neither eliminates the root formatting conflicts on its own.
For more robust agent pipelines, using native tool-calling agents where supported offers a cleaner architecture by moving tool dispatching from free-form prompt text to structured API interactions.
Frequently Asked Questions
Why does the OutputParserException regarding a final answer and parse-able action occur in LangChain?
This exception occurs when an LLM produces both an action pattern (like Action: and Action Input:) and a final answer prefix (Final Answer:) in a single output turn. Because the ReAct parser checks for both conditions and finds both to be true, it cannot determine whether to invoke a tool via an AgentAction or end execution with an AgentFinish, causing it to abort and raise the error.
What issue can arise when only handle_parsing_errors=True is passed to initialize_agent?
Passing handle_parsing_errors=True catches the OutputParserException and returns the error message (or a fallback like “Invalid or incomplete response”) back into the scratchpad as an observation. However, it does not prevent an over-generating model from continuing to hallucinate Thought/Action/Action Input/Observation cycles on subsequent turns instead of cleanly resolving.
What is the difference between handle_parsing_errors and early_stopping_method?
handle_parsing_errors manages runtime parser failures when an OutputParserException is raised by feeding error feedback or a custom observation back to the model. early_stopping_method is an independent setting that controls how the execution terminates once max_iterations or max_execution_time has been reached.
What is the underlying root cause of turn ambiguity in ReActSingleInputOutputParser?
The root cause is the LLM over-generating text across turn boundaries rather than yielding control after emitting an action or a final answer. When the model outputs both action patterns and termination keywords in the same turn, the parser’s regex and string checks match both mutually exclusive states.
Keep reading: LLM Agents & Tooling
- Troubleshooting CrewAI ValidationError: Please Provide an OpenAI API Key — Fix CrewAI ValidationError: Please provide an OpenAI API key when setting memory=True by providing an OPENAI_API_KEY or configuring a custom embedder.
- Troubleshooting ChromaDB InvalidDimensionException: Resolving the 1536 vs 384 Dimension Mismatch — Fix ChromaDB InvalidDimensionException where embedding dimension 1536 does not match collection dimensionality 384 by explicitly setting the…
- Troubleshooting LangGraph InvalidUpdateError: Resolving Concurrent State Updates with Annotated Reducers — Fix langgraph.errors.InvalidUpdateError in LangGraph. Learn how to resolve concurrent state write collisions using Annotated keys and reducer…
- Resolving Pydantic State Deserialization Failures in LangGraph Checkpointers — Pydantic state turning into a raw dict in LangGraph checkpoints? Four causes: msgpack allowlist, unimportable classes, schema drift, unserializable…
All guides in this series: LLM Agent Guides: LangChain, LangGraph & AI Tooling

Leave a Reply