{"record":{"id":"e87f4010a66a259f","repo":"BerriAI/litellm","slug":"dynamic-api-key-needs-to-be-a-string-got-type-ty","errorCode":null,"errorMessage":"dynamic_api_key needs to be a string. Got type={type(dynamic_api_key).__name__}","messagePattern":"dynamic_api_key needs to be a string\\. Got type=(.+?)","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"litellm/litellm_core_utils/get_llm_provider_logic.py","lineNumber":227,"sourceCode":"            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\"\n                        dynamic_api_key = get_secret_str(\"MISTRAL_API_KEY\")\n                    elif endpoint == \"api.groq.com/openai/v1\":","sourceCodeStart":209,"sourceCodeEnd":245,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/litellm_core_utils/get_llm_provider_logic.py#L209-L245","documentation":"Type guard alongside the api_base check: for provider-prefixed models, dynamic_api_key must be a string when provided. Passing any non-string (dict, bytes, object) raises this Exception (surfacing as BadRequestError via the wrapper).","triggerScenarios":"litellm.completion(model='openai/m', api_key={'key': ...}) where api_key propagates as dynamic_api_key, or config pipelines passing a secret object/SecretStr instead of its string value.","commonSituations":"Pydantic SecretStr not unwrapped (.get_secret_value() forgotten), config YAML nesting the key under an object, or passing an os.environ mapping instead of a value.","solutions":["Unwrap secret objects to strings before the call (e.g. secret.get_secret_value()).","Pass api_key as a plain string literal or env-var string.","Add a config-time assertion that api_key is a str."],"exampleFix":"# before\nlitellm.completion(model='openai/m', api_key=SecretStr('sk-...'), ...)\n\n# after\nlitellm.completion(model='openai/m', api_key=secret.get_secret_value(), ...)","handlingStrategy":"validation","validationCode":"def api_key_valid(api_key) -> bool:\n    return api_key is None or isinstance(api_key, str)","typeGuard":"function isApiKey(v: unknown): v is string | undefined {\n  return v === undefined || v === null || typeof v === 'string';\n}","tryCatchPattern":null,"preventionTips":["Unwrap SecretStr with get_secret_value() before passing.","Decode bytes secrets to str at the config boundary.","Never pass credential objects; pass their token string."],"tags":["validation","api-key","type-error","secrets"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}