{"record":{"id":"8c5c5b421ffdc6c4","repo":"BerriAI/litellm","slug":"could-not-extract-a-message-from-the-langflow-resp","errorCode":null,"errorMessage":"Could not extract a message from the LangFlow response; ensure the flow ends in a Chat Output component","messagePattern":"Could not extract a message from the LangFlow response; ensure the flow ends in a Chat Output component","errorType":"http","errorClass":"LangFlowError","httpStatus":500,"severity":"error","filePath":"litellm/llms/langflow/chat/transformation.py","lineNumber":242,"sourceCode":"        optional_params: dict,\n        litellm_params: dict,\n        encoding: Any,\n        api_key: str | None = None,\n        json_mode: bool | None = None,\n    ) -> ModelResponse:\n        try:\n            response_json: Final = raw_response.json()\n        except Exception as e:\n            raise LangFlowError(\n                message=f\"LangFlow returned a non-JSON response: {e}\",\n                status_code=raw_response.status_code,\n            )\n\n        verbose_logger.debug(\"LangFlow response: %s\", response_json)\n\n        content: Final = self._extract_content_from_response(response_json)\n        if content is None:\n            raise LangFlowError(\n                message=(\n                    \"Could not extract a message from the LangFlow response; \"\n                    \"ensure the flow ends in a Chat Output component\"\n                ),\n                status_code=500,\n            )\n\n        message: Final = Message(content=content, role=\"assistant\")\n        choice: Final = Choices(finish_reason=\"stop\", index=0, message=message)\n\n        model_response.choices = [choice]\n        model_response.model = model\n\n        try:\n            from litellm.utils import token_counter\n\n            prompt_tokens: Final = token_counter(model=model, messages=messages)\n            completion_tokens: Final = token_counter(model=model, text=content, count_response_tokens=True)","sourceCodeStart":224,"sourceCodeEnd":260,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/llms/langflow/chat/transformation.py#L224-L260","documentation":"After a successful JSON parse, _extract_content_from_response walks outputs[0].outputs[0].results.message.text (with a fallback over outputs values). If no message text is found it returns None and transform_response raises LangFlowError(500). It means the flow executed but its result shape contains no Chat Output message, so litellm refuses to return a raw JSON blob as the assistant answer.","triggerScenarios":"The LangFlow flow's final component is a Text or Data output instead of Chat Output; the flow errored internally and returned outputs without message text; output_type in the payload (default 'chat') does not match how the flow was built; a LangFlow version whose run response schema differs.","commonSituations":"Exporting a flow template built around text components; renaming/replacing the output component after wiring; flow works in the LangFlow UI playground but its endpoint output shape changed after edits.","solutions":["Open the flow in LangFlow and make the final component a Chat Output component","Run the same input in the LangFlow UI playground and confirm the response JSON contains outputs[0].outputs[0].results.message.text","Match output_type to the flow (chat vs text) via the optional param if the flow was built for text","Check the LangFlow server logs for an in-flow error that produced empty outputs"],"exampleFix":"# before: flow ends in Text output -> no message.text -> LangFlowError 500\n# fix in LangFlow UI: delete Text Output, add Chat Output, reconnect, save, then:\nresp = litellm.completion(\n    model=\"langflow/my-flow\",\n    messages=[{\"role\": \"user\", \"content\": \"hi\"}],\n)\nprint(resp.choices[0].message.content)","handlingStrategy":"try-catch","validationCode":"import httpx\n\n# smoke-test the flow's output shape before wiring it into litellm\ndef langflow_flow_emits_chat_output(base: str, flow_id: str, api_key: str | None) -> bool:\n    r = httpx.post(\n        f\"{base.rstrip('/')}/api/v1/run/{flow_id}\",\n        headers={\"x-api-key\": api_key} if api_key else {},\n        json={\"input_value\": \"ping\", \"input_type\": \"chat\", \"output_type\": \"chat\"},\n        timeout=30,\n    )\n    body = r.json()\n    try:\n        return bool(body[\"outputs\"][0][\"outputs\"][0][\"results\"][\"message\"][\"text\"])\n    except (KeyError, IndexError, TypeError):\n        return False","typeGuard":null,"tryCatchPattern":"from litellm.llms.langflow.chat.transformation import LangFlowError\n\ntry:\n    resp = litellm.completion(model=\"langflow/<flow_id>\", messages=msgs, api_base=base)\nexcept LangFlowError as e:\n    if \"Could not extract a message\" in e.message:\n        raise FlowConfigError(\"Flow must end in a Chat Output component\") from e\n    raise","preventionTips":["Verify every flow ends in a Chat Output component before registering it with a langflow/ model name","Add an integration test that runs one prompt per flow and asserts non-empty choices[0].message.content","Pin the LangFlow version so response schemas do not drift under you"],"tags":["langflow","response-parsing","chat-output","flow-configuration"],"backgroundTag":"response-parsing-failed","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}