{"record":{"id":"f0eece03eb18df5b","repo":"langchain-ai/langchain","slug":"could-not-parse-function-call-exc","errorCode":null,"errorMessage":"Could not parse function call: {exc}","messagePattern":"Could not parse function call: (.+?)","errorType":"exception","errorClass":"OutputParserException","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/output_parsers/openai_functions.py","lineNumber":51,"sourceCode":"            result: The result of the LLM call.\n            partial: Whether to parse partial JSON objects.\n\n        Returns:\n            The parsed JSON object.\n\n        Raises:\n            OutputParserException: If the output is not valid JSON.\n        \"\"\"\n        generation = result[0]\n        if not isinstance(generation, ChatGeneration):\n            msg = \"This output parser can only be used with a chat generation.\"\n            raise OutputParserException(msg)\n        message = generation.message\n        try:\n            func_call = copy.deepcopy(message.additional_kwargs[\"function_call\"])\n        except KeyError as exc:\n            msg = f\"Could not parse function call: {exc}\"\n            raise OutputParserException(msg) from exc\n\n        if self.args_only:\n            return func_call[\"arguments\"]\n        return func_call\n\n\nclass JsonOutputFunctionsParser(BaseCumulativeTransformOutputParser[Any]):\n    \"\"\"Parse an output as the JSON object.\"\"\"\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    args_only: bool = True","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/output_parsers/openai_functions.py#L33-L69","documentation":"The OpenAI-functions output parser reads `message.additional_kwargs[\"function_call\"]`; if the key is absent, the KeyError is caught and re-raised as OutputParserException with `Could not parse function call: 'function_call'`. This means the model did not emit a (legacy) function call at all — the message is plain content or uses modern `tool_calls` instead — so there is nothing for this parser to extract.","triggerScenarios":"The model answered in plain text instead of invoking the bound function; the chain bound `tools` (modern tool calling, which populates `tool_calls`) while the parser expects legacy `function_call`; function calling not enabled on the endpoint/model.","commonSituations":"Using newer models/endpoints that only support the `tools` API with the older `create_openai_fn_chain`/function_call parser; prompts that let the model answer directly instead of forcing a call (`function_call={\"name\": ...}` / `tool_choice` not set); models that hallucinate an answer instead of calling.","solutions":["Force the call: bind the function with `tool_choice`/`function_call` set to the required function so the model must emit it.","If the model uses modern tool calling, switch to reading `message.tool_calls` or `JsonOutputFunctionsParser`-era helpers replaced by `with_structured_output` — do not use this legacy parser.","Catch OutputParserException and handle the no-call case (e.g. surface the model's text answer or retry with stronger instructions).","Verify the model/endpoint supports function calling at all (e.g. some local/OSS endpoints return text)."],"exampleFix":"// before\nllm = ChatOpenAI(model=\"gpt-4o\")\nchain = prompt | llm | OpenAIFunctionCallerOutputParser()\n\n// after (modern tool calling)\nfrom pydantic import BaseModel\nclass Sentiment(BaseModel):\n    label: str\nchain = prompt | llm.with_structured_output(Sentiment, method=\"function_calling\")","handlingStrategy":"try-catch","validationCode":"def has_function_call(message) -> bool:\n    return \"function_call\" in getattr(message, \"additional_kwargs\", {})\n\n# before parsing\nif not has_function_call(result[0].message):\n    raise ValueError(\"model returned no function call; inspect message.content\")","typeGuard":"def has_legacy_function_call(msg) -> bool:\n    return isinstance(getattr(msg, \"additional_kwargs\", {}).get(\"function_call\"), dict)","tryCatchPattern":"from langchain_core.exceptions import OutputParserException\n\ntry:\n    out = parser.parse_result(result)\nexcept OutputParserException as e:\n    if \"function_call\" in str(e):\n        msg = result[0].message\n        if msg.tool_calls:  # modern API responded\n            out = msg.tool_calls[0][\"args\"]\n        else:\n            out = retry_with_forced_tool_choice(chain)  # bind tool_choice='required'","preventionTips":["Bind the function with tool_choice/function_call forced when a call is mandatory","Migrate to bind_tools/with_structured_output instead of the legacy parser","Verify the endpoint supports function calling before building the chain"],"tags":["output-parsers","openai","function-calling","legacy","llm-output"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}