{"record":{"id":"2fd924630369fb96","repo":"BerriAI/litellm","slug":"dynamic-api-key-needs-to-be-a-string-dynamic-api","errorCode":null,"errorMessage":"dynamic_api_key needs to be a string. dynamic_api_key={dynamic_api_key}","messagePattern":"dynamic_api_key needs to be a string\\. dynamic_api_key=(.+?)","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"litellm/litellm_core_utils/get_llm_provider_logic.py","lineNumber":356,"sourceCode":"                        custom_llm_provider = \"hyperbolic\"\n                        dynamic_api_key = get_secret_str(\"HYPERBOLIC_API_KEY\")\n                    elif endpoint == \"https://ai-gateway.vercel.sh/v1\":\n                        custom_llm_provider = \"vercel_ai_gateway\"\n                        dynamic_api_key = get_secret_str(\"VERCEL_AI_GATEWAY_API_KEY\")\n                    elif endpoint == \"https://api.inference.wandb.ai/v1\":\n                        custom_llm_provider = \"wandb\"\n                        dynamic_api_key = get_secret_str(\"WANDB_API_KEY\")\n                    elif endpoint == \"https://pinstripes.io/v1\":\n                        custom_llm_provider = \"pinstripes\"\n                        dynamic_api_key = get_secret_str(\"PINSTRIPES_API_KEY\")\n                    elif endpoint == \"https://api.meta.ai/v1\":\n                        custom_llm_provider = \"meta\"\n                        dynamic_api_key = get_secret_str(\"META_API_KEY\")\n\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. dynamic_api_key={dynamic_api_key}\")\n                    return model, custom_llm_provider, dynamic_api_key, api_base\n\n        # check if model in known model provider list  -> for huggingface models, raise exception as they don't have a fixed provider (can be togetherai, anyscale, baseten, runpod, et.)\n        ## openai - chatcompletion + text completion\n        if (\n            model in litellm.open_ai_chat_completion_models\n            or \"ft:gpt-3.5-turbo\" in model\n            or \"ft:gpt-4\" in model  # catches ft:gpt-4-0613, ft:gpt-4o\n            or model in litellm.openai_image_generation_models\n            or model.startswith(\"gpt-image\")\n            or model in litellm.openai_video_generation_models\n        ):\n            custom_llm_provider = \"openai\"\n        elif model in litellm.open_ai_text_completion_models:\n            custom_llm_provider = \"text-completion-openai\"\n        ## anthropic\n        elif model in litellm.anthropic_models:\n            if litellm.AnthropicTextConfig._is_anthropic_text_model(model):","sourceCodeStart":338,"sourceCodeEnd":374,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/litellm_core_utils/get_llm_provider_logic.py#L338-L374","documentation":"dynamic_api_key string check on the OpenAI-compatible-endpoint path: after resolving a known endpoint (perplexity/deepinfra/wandb/meta/...), the dynamic_api_key resolved from arguments or env is not a string.","triggerScenarios":"Provider endpoint matched but a non-string api_key object was supplied, or a get_secret_str-style lookup returned a non-string object injected by custom secret tooling.","commonSituations":"Secret managers returning objects/bytes, Pydantic SecretStr, or config loading code that stores credentials as dicts.","solutions":["Ensure the api_key argument is the string value of the credential.","Decode bytes keys: api_key.decode() where applicable.","Unwrap SecretStr via get_secret_value()."],"exampleFix":"# before\nlitellm.completion(model='openai/...', api_base='https://api.deepinfra.com/v1/openai', api_key=b'sk-...')\n\n# after\nlitellm.completion(model='openai/...', api_base='https://api.deepinfra.com/v1/openai', api_key='sk-...')","handlingStrategy":"validation","validationCode":"def resolved_key_is_str(key) -> bool:\n    return key is None or isinstance(key, str)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Normalize secrets to str at ingestion from secret managers.","Prefer env-var string resolution over injecting objects.","Add a preflight check over call kwargs: all values str or None."],"tags":["validation","api-key","openai-compatible","secrets"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}