{"record":{"id":"d5f945e0dcdfe485","repo":"BerriAI/litellm","slug":"api-base-needs-to-be-a-string-api-base-api-base","errorCode":null,"errorMessage":"api base needs to be a string. api_base={api_base}","messagePattern":"api base needs to be a string\\. api_base=(.+?)","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"litellm/litellm_core_utils/get_llm_provider_logic.py","lineNumber":225,"sourceCode":"\n        if (\n            model.split(\"/\", 1)[0] in litellm.provider_list\n            and model.split(\"/\", 1)[0] not in litellm.model_list_set\n            and len(model.split(\"/\"))\n            > 1  # handle edge case where user passes in `litellm --model mistral` https://github.com/BerriAI/litellm/issues/1351\n        ):\n            return _get_openai_compatible_provider_info(\n                model=model,\n                api_base=api_base,\n                api_key=api_key,\n                dynamic_api_key=dynamic_api_key,\n                litellm_params=litellm_params,\n            )\n        elif model.split(\"/\", 1)[0] in litellm.provider_list:\n            custom_llm_provider = model.split(\"/\", 1)[0]\n            model = model.split(\"/\", 1)[1]\n            if api_base is not None and not isinstance(api_base, str):\n                raise Exception(f\"api base needs to be a string. api_base={api_base}\")\n            if dynamic_api_key is not None and not isinstance(dynamic_api_key, str):\n                raise Exception(f\"dynamic_api_key needs to be a string. Got type={type(dynamic_api_key).__name__}\")\n            return model, custom_llm_provider, dynamic_api_key, api_base\n        # check if api base is a known openai compatible endpoint\n        if api_base:\n            for endpoint in litellm.openai_compatible_endpoints:\n                if _endpoint_matches_api_base(endpoint, api_base):\n                    if endpoint == \"api.perplexity.ai\":\n                        custom_llm_provider = \"perplexity\"\n                        dynamic_api_key = get_secret_str(\"PERPLEXITYAI_API_KEY\")\n                    elif endpoint == \"api.endpoints.anyscale.com/v1\":\n                        custom_llm_provider = \"anyscale\"\n                        dynamic_api_key = get_secret_str(\"ANYSCALE_API_KEY\")\n                    elif endpoint == \"api.deepinfra.com/v1/openai\":\n                        custom_llm_provider = \"deepinfra\"\n                        dynamic_api_key = get_secret_str(\"DEEPINFRA_API_KEY\")\n                    elif endpoint == \"api.mistral.ai/v1\":\n                        custom_llm_provider = \"mistral\"","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/litellm_core_utils/get_llm_provider_logic.py#L207-L243","documentation":"Type guard in get_llm_provider for the 'provider/model' path: the model prefix matched a known provider, but the supplied api_base is not a string (e.g. a dict, list, or number). The bare Exception is re-raised as BadRequestError ('GetLLMProvider Exception - api base needs to be a string...') by the enclosing handler.","triggerScenarios":"litellm.completion(model='openai/llama3', api_base={'url': ...}) or any provider-prefixed model where api_base comes from config as a non-string type (dict from YAML, None-adjacent objects, Pydantic objects).","commonSituations":"Config files storing api_base as a structured object, programmatic config where the wrong key is passed, or deserialized JSON config with nested objects.","solutions":["Pass api_base as a plain string: api_base='http://host:8000/v1'.","If config is structured, extract the string field first (config['api_base']['url']).","Validate config at load time with a schema that types api_base as string."],"exampleFix":"# before\nlitellm.completion(model='openai/m', api_base={'url': 'http://x:8000/v1'}, ...)\n\n# after\nlitellm.completion(model='openai/m', api_base='http://x:8000/v1', ...)","handlingStrategy":"validation","validationCode":"def api_base_valid(api_base) -> bool:\n    return api_base is None or isinstance(api_base, str)","typeGuard":"function isApiBase(v: unknown): v is string | undefined {\n  return v === undefined || v === null || typeof v === 'string';\n}","tryCatchPattern":null,"preventionTips":["Type api_base as Optional[str] in config models so non-strings fail at load time.","Extract the URL string from structured config before building call kwargs.","Add startup config validation for provider settings."],"tags":["validation","api-base","type-error","config"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}