{"record":{"id":"d377abf4bdc0b1e4","repo":"BerriAI/litellm","slug":"voyage-api-key-is-required-for-multimodal-embeddin","errorCode":null,"errorMessage":"Voyage API key is required for multimodal embeddings. Set VOYAGE_API_KEY / VOYAGE_AI_API_KEY / VOYAGE_AI_TOKEN or pass `api_key` explicitly.","messagePattern":"Voyage API key is required for multimodal embeddings\\. Set VOYAGE_API_KEY / VOYAGE_AI_API_KEY / VOYAGE_AI_TOKEN or pass `api_key` explicitly\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/llms/voyage/embedding/transformation_multimodal.py","lineNumber":94,"sourceCode":"\n    def validate_environment(\n        self,\n        headers: dict,\n        model: str,\n        messages: list[AllMessageValues],\n        optional_params: dict,\n        litellm_params: dict,\n        api_key: str | None = None,\n        api_base: str | None = None,\n    ) -> dict:\n        if api_key is None:\n            api_key = (\n                get_secret_str(\"VOYAGE_API_KEY\")\n                or get_secret_str(\"VOYAGE_AI_API_KEY\")\n                or get_secret_str(\"VOYAGE_AI_TOKEN\")\n            )\n        if not api_key:\n            raise ValueError(\n                \"Voyage API key is required for multimodal embeddings. \"\n                \"Set VOYAGE_API_KEY / VOYAGE_AI_API_KEY / VOYAGE_AI_TOKEN \"\n                \"or pass `api_key` explicitly.\"\n            )\n        return {\"Authorization\": f\"Bearer {api_key}\"}\n\n    def _normalize_content_item(self, item: dict[str, Any]) -> dict[str, Any]:\n        item_type: Final = item.get(\"type\")\n        if item_type == \"image_url\":\n            image_url = item.get(\"image_url\")\n            if isinstance(image_url, dict):\n                image_url = image_url.get(\"url\")\n            if image_url is None:\n                raise ValueError(\n                    \"Voyage multimodal embeddings require a non-empty `image_url`. \"\n                    \"Got an image content block without a `url`.\"\n                )\n            if isinstance(image_url, str) and image_url.startswith(\"data:image/\"):","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/llms/voyage/embedding/transformation_multimodal.py#L76-L112","documentation":"Voyage multimodal embeddings (VoyageMultimodalEmbeddingConfig.validate_environment) build an Authorization: Bearer header. The key is taken from the api_key argument or the env chain VOYAGE_API_KEY, VOYAGE_AI_API_KEY, VOYAGE_AI_TOKEN; if all are empty, this ValueError is raised before the request is sent. Multimodal embedding calls need this even when text-only embedding calls elsewhere in the app already work.","triggerScenarios":"litellm.embedding(model=\"voyage-3-multimodal\", input=[{\"content\": [...]}]) with no api_key and none of the three Voyage env vars set; using the older VOYAGE_AI_TOKEN name after an env cleanup; serverless functions that do not inherit local shell env.","commonSituations":"Adding image embedding to an existing text pipeline where the key was only configured for a different provider; typos in env var names; deploying to Vercel/Lambda without migrating the secret.","solutions":["Export VOYAGE_API_KEY (or VOYAGE_AI_API_KEY / VOYAGE_AI_TOKEN) in the runtime environment.","Or pass api_key directly to the embedding call.","Store the secret in the platform's secret manager and inject it as VOYAGE_API_KEY at startup.","Add a startup assertion: assert os.environ.get('VOYAGE_API_KEY'), 'VOYAGE_API_KEY missing'."],"exampleFix":"# before\nresp = litellm.embedding(\n    model=\"voyage-3-multimodal\",\n    input=[{\"content\": [{\"type\": \"text\", \"text\": \"cat\"}, {\"type\": \"image_url\", \"image_url\": \"https://...\"}]}],\n)\n# -> ValueError: Voyage API key is required for multimodal embeddings...\n\n# after\nresp = litellm.embedding(\n    model=\"voyage-3-multimodal\",\n    input=[{\"content\": [{\"type\": \"text\", \"text\": \"cat\"}, {\"type\": \"image_url\", \"image_url\": \"https://...\"}]}],\n    api_key=os.environ[\"VOYAGE_API_KEY\"],\n)","handlingStrategy":"validation","validationCode":"import os\n\nVOYAGE_KEY = (\n    os.getenv(\"VOYAGE_API_KEY\")\n    or os.getenv(\"VOYAGE_AI_API_KEY\")\n    or os.getenv(\"VOYAGE_AI_TOKEN\")\n)\nif not VOYAGE_KEY:\n    raise RuntimeError(\"Voyage multimodal embedding requires VOYAGE_API_KEY\")\nresp = litellm.embedding(model=\"voyage-3-multimodal\", input=inputs, api_key=VOYAGE_KEY)","typeGuard":"const hasVoyageKey = (env: Record<string, string | undefined>): boolean =>\n  Boolean(env.VOYAGE_API_KEY ?? env.VOYAGE_AI_API_KEY ?? env.VOYAGE_AI_TOKEN);","tryCatchPattern":"try:\n    resp = litellm.embedding(model=\"voyage-3-multimodal\", input=inputs)\nexcept ValueError as e:\n    if \"Voyage API key is required\" in str(e):\n        raise RuntimeError(\"Set VOYAGE_API_KEY for multimodal embeddings\") from e\n    raise","preventionTips":["Set VOYAGE_API_KEY in every runtime that touches Voyage models, including serverless.","Fail fast at startup with an env assertion instead of discovering it mid-request.","Remember multimodal embeddings have their own key check even if text embeddings already work."],"tags":["voyage","multimodal","embedding","api-key","authentication","litellm"],"backgroundTag":"missing-api-key","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}