{"record":{"id":"d785cfca5425a9da","repo":"langchain-ai/langchain","slug":"exceptions-joined-with-n-n","errorCode":null,"errorMessage":"{exceptions joined with '\\n\\n'}","messagePattern":"\\{exceptions joined with '\\\\n\\\\n'\\}","errorType":"exception","errorClass":"OutputParserException","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/output_parsers/openai_tools.py","lineNumber":135,"sourceCode":"        The parsed tool calls.\n\n    Raises:\n        OutputParserException: If any of the tool calls are not valid JSON.\n    \"\"\"\n    final_tools: list[dict[str, Any]] = []\n    exceptions = []\n    for tool_call in raw_tool_calls:\n        try:\n            parsed = parse_tool_call(\n                tool_call, partial=partial, strict=strict, return_id=return_id\n            )\n            if parsed:\n                final_tools.append(parsed)\n        except OutputParserException as e:\n            exceptions.append(str(e))\n            continue\n    if exceptions:\n        raise OutputParserException(\"\\n\\n\".join(exceptions))\n    return final_tools\n\n\nclass JsonOutputToolsParser(BaseCumulativeTransformOutputParser[Any]):\n    \"\"\"Parse tools from OpenAI response.\"\"\"\n\n    strict: bool = False\n    \"\"\"Whether to allow non-JSON-compliant strings.\n\n    See: https://docs.python.org/3/library/json.html#encoders-and-decoders\n\n    Useful when the parsed output may include unicode characters or new lines.\n    \"\"\"\n\n    return_id: bool = False\n    \"\"\"Whether to return the tool call id.\"\"\"\n\n    first_tool_only: bool = False","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/output_parsers/openai_tools.py#L117-L153","documentation":"Raised by parse_tool_calls when one or more raw tool calls fail parsing: each individual OutputParserException (e.g. error 189) is collected as a string, and all are joined with blank lines into a single OutputParserException. This aggregates multi-tool-call failures so you see every broken argument payload at once.","triggerScenarios":"A model response containing multiple tool_calls where at least one has invalid JSON arguments; parse_tool_calls(raw_tool_calls, partial=False) on responses from models with unreliable JSON emission.","commonSituations":"Parallel tool calling with one malformed payload; token-limit truncation affecting one of several calls; parsing cached/replayed raw responses captured from older API formats.","solutions":["Read the combined message to identify which tool call(s) failed, then fix the cause (usually max_tokens truncation or model JSON quality)","Increase max_tokens and retry the request","Use the higher-level AIMessage.tool_calls / invalid_tool_calls surface, which isolates bad calls instead of raising, when you want per-call resilience"],"exampleFix":"# before\ncalls = parse_tool_calls(message.additional_kwargs[\"tool_calls\"])  # raises if any call is bad\n\n# after\nfor tc, itc in zip(message.tool_calls, message.invalid_tool_calls or []):\n    if itc:\n        log.warning(\"bad tool call\", itc.error)\n# message.tool_calls contains only the successfully parsed calls","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    calls = parse_tool_calls(raw_tool_calls)\nexcept OutputParserException as e:\n    # e.message lists every failure; fall back to per-call parsing\n    calls = []\n    for rc in raw_tool_calls:\n        try:\n            calls.append(parse_tool_call(rc))\n        except OutputParserException:\n            continue","preventionTips":["Prefer AIMessage.tool_calls/invalid_tool_calls for per-call isolation","Parse the aggregated message to identify which calls failed before retrying"],"tags":["tool-calling","json","output-parsing","aggregation"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}