{"record":{"id":"548149a0db888216","repo":"BerriAI/litellm","slug":"flow-id-cannot-be-set-via-request-parameters-use","errorCode":null,"errorMessage":"flow_id cannot be set via request parameters; use model langflow/{flow_id}","messagePattern":"flow_id cannot be set via request parameters; use model langflow/(.+?)","errorType":"validation","errorClass":"LangFlowError","httpStatus":400,"severity":"error","filePath":"litellm/llms/langflow/chat/transformation.py","lineNumber":75,"sourceCode":"\n    def map_openai_params(\n        self,\n        non_default_params: dict,\n        optional_params: dict,\n        model: str,\n        drop_params: bool,\n    ) -> dict:\n        return optional_params\n\n    def _get_flow_id(self, model: str, optional_params: dict) -> str:\n        \"\"\"\n        Extract flow_id from the authorized model name only.\n\n        Model format: \"langflow/{flow_id}\". Request kwargs must not override\n        flow_id (would allow calling another flow with the same API key).\n        \"\"\"\n        if optional_params.get(\"flow_id\") is not None:\n            raise LangFlowError(\n                status_code=400,\n                message=(\"flow_id cannot be set via request parameters; use model langflow/{flow_id}\"),\n            )\n\n        flow_id: Final = (model.split(\"/\", 1)[1] if \"/\" in model else model).strip()\n        if not flow_id:\n            raise LangFlowError(\n                status_code=400,\n                message=\"flow_id is required; use model langflow/{flow_id}\",\n            )\n        return flow_id\n\n    def get_complete_url(\n        self,\n        api_base: str | None,\n        api_key: str | None,\n        model: str,\n        optional_params: dict,","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/langflow/chat/transformation.py#L57-L93","documentation":"LiteLLM's LangFlow integration extracts the target flow exclusively from the model string ('langflow/{flow_id}'). Passing flow_id as a request parameter (e.g. in extra_body or kwargs, which land in optional_params) is rejected with HTTP 400 because it would let a caller redirect a shared API key to a different flow. The check happens in _get_flow_id before any HTTP request is made.","triggerScenarios":"Calling litellm.completion(model=\"langflow/my-flow\", ..., flow_id=\"other-flow\"), or passing flow_id via extra_body={'flow_id': ...}, api_key-level defaults, or router default_params that inject flow_id into optional_params.","commonSituations":"Migrating from a client that sent flow_id as a body parameter directly to the LangFlow REST API; putting flow_id in a router's default_params so it gets merged into every request; a generic OpenAI-compatible wrapper forwarding all kwargs.","solutions":["Remove flow_id from the request kwargs / extra_body and encode it in the model name: model=\"langflow/{flow_id}\"","If using a router, check default_params and extra_body templates for a stale flow_id entry","Verify no middleware or OpenAI-compatible shim is injecting flow_id into the payload"],"exampleFix":"# before\nlitellm.completion(model=\"langflow/abc-123\", messages=msgs, flow_id=\"abc-123\")\n\n# after\nlitellm.completion(model=\"langflow/abc-123\", messages=msgs)","handlingStrategy":"validation","validationCode":"def safe_langflow_call(model: str, extra_body: dict | None = None) -> None:\n    if \"/\" not in model or not model.split(\"/\", 1)[1].strip():\n        raise ValueError(f\"model must be langflow/{{flow_id}}, got: {model!r}\")\n    body = extra_body or {}\n    if \"flow_id\" in body:\n        raise ValueError(\"flow_id must not be passed via extra_body; encode it in the model name\")","typeGuard":"def is_valid_langflow_model(model: str) -> bool:\n    return isinstance(model, str) and len(model.split(\"/\", 1)) == 2 and bool(model.split(\"/\", 1)[1].strip())","tryCatchPattern":"from litellm.llms.langflow.chat.transformation import LangFlowError\ntry:\n    litellm.completion(model=f\"langflow/{flow_id}\", messages=msgs)\nexcept LangFlowError as e:\n    if e.status_code == 400 and \"flow_id cannot be set\" in str(e):\n        # strip flow_id from kwargs and retry once with model-only routing\n        ...","preventionTips":["Centralize model-string construction: always f\"langflow/{flow_id}\" from a config lookup, never accept flow_id from request bodies","Lint router default_params / extra_body templates for forbidden keys (flow_id, tweaks)","Document for API consumers that langflow models take no provider-specific body params"],"tags":["langflow","validation","security","config"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}