BerriAI/litellm · error · ValueError

api_base is required for LangFlow. Set it via…

Error message

api_base is required for LangFlow. Set it via LANGFLOW_API_BASE env var or api_base parameter.

What it means

Raised by LangFlowConfig.get_complete_url when building the LangFlow run URL ({api_base}/api/v1/run/{flow_id}) with api_base=None. LiteLLM cannot form a request without a base URL, so it raises ValueError instead of guessing. The base URL is normally resolved from the api_base parameter or the LANGFLOW_API_BASE environment variable.

Solutions

  1. Pass api_base explicitly: litellm.completion(model="langflow/<flow_id>", api_base="http://localhost:7860", ...)
  2. Or set the env var in the process that makes the call: export LANGFLOW_API_BASE=http://localhost:7860, then restart the process
  3. If calling through the LiteLLM proxy, add api_base to the langflow model deployment in config.yaml
  4. Verify the variable is visible in the same process: printenv LANGFLOW_API_BASE

Example fix

// before
response = litellm.completion(
    model="langflow/abc123-flow-id",
    messages=[{"role": "user", "content": "hi"}],
)  # ValueError: api_base is required for LangFlow

// after
response = litellm.completion(
    model="langflow/abc123-flow-id",
    messages=[{"role": "user", "content": "hi"}],
    api_base="http://localhost:7860",  # or export LANGFLOW_API_BASE=http://localhost:7860
)
Defensive patterns

Strategy: validation

Validate before calling

import os

LANGFLOW_BASE = os.getenv("LANGFLOW_API_BASE")
if not LANGFLOW_BASE:
    raise SystemExit("Set LANGFLOW_API_BASE before starting (e.g. http://localhost:7860)")
# then: litellm.completion(model="langflow/<flow_id>", api_base=LANGFLOW_BASE, ...)

Try / catch

try:
    litellm.completion(model="langflow/<flow_id>", messages=msgs, api_base=base)
except ValueError as e:
    if "api_base is required" in str(e):
        raise ConfigError("LANGFLOW_API_BASE missing") from e
    raise

Prevention

When it happens

Trigger: Any langflow completion call (e.g. litellm.completion(model="langflow/<flow_id>", ...)) where the URL-building path receives no api_base: neither an api_base kwarg nor a resolvable LANGFLOW_API_BASE env var reached get_complete_url (for example when the config is invoked directly, bypassing _get_openai_compatible_provider_info which would otherwise default to http://localhost:7860).

Common situations: LANGFLOW_API_BASE exported in one shell but the proxy/worker/container runs in a different environment; .env file not loaded by the process; typo in the variable name (e.g. LANGFLOW_APIBASE); passing the base URL under a kwarg the config does not read.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/db221b199d3fef2a. Report an issue: GitHub.

Appendix: source

Thrown at litellm/llms/langflow/chat/transformation.py:98

        flow_id: Final = (model.split("/", 1)[1] if "/" in model else model).strip()
        if not flow_id:
            raise LangFlowError(
                status_code=400,
                message="flow_id is required; use model langflow/{flow_id}",
            )
        return flow_id

    def get_complete_url(
        self,
        api_base: str | None,
        api_key: str | None,
        model: str,
        optional_params: dict,
        litellm_params: dict,
        stream: bool | None = None,
    ) -> str:
        if api_base is None:
            raise ValueError(
                "api_base is required for LangFlow. Set it via LANGFLOW_API_BASE env var or api_base parameter."
            )

        api_base = api_base.rstrip("/")
        flow_id: Final = quote(self._get_flow_id(model, optional_params), safe="")
        return f"{api_base}/api/v1/run/{flow_id}"

    def _get_last_user_message(self, messages: list[AllMessageValues]) -> str:
        """Extract the text of the last user message to use as input_value."""
        for msg in reversed(messages):
            if msg.get("role") == "user":
                content = msg.get("content", "")
                if isinstance(content, list):
                    content = convert_content_list_to_str(msg)
                if not isinstance(content, str):
                    content = str(content)
                return content

View on GitHub (pinned to 77b7c6c40c)