{"record":{"id":"505138572a0ad5ab","repo":"BerriAI/litellm","slug":"custom-llm-provider-capitalize-exception-badreq","errorCode":null,"errorMessage":"{custom_llm_provider.capitalize()}Exception BadRequestError - {error_str}","messagePattern":"(.+?)Exception BadRequestError - (.+?)","errorType":"exception","errorClass":"BadRequestError","httpStatus":403,"severity":"error","filePath":"litellm/litellm_core_utils/exception_mapping_utils.py","lineNumber":1131,"sourceCode":"            message=f\"litellm.InternalServerError: {custom_llm_provider}Exception - {error_str}\",\n            model=model,\n            llm_provider=custom_llm_provider,\n            response=httpx.Response(\n                status_code=500,\n                content=str(original_exception),\n                request=httpx.Request(method=\"completion\", url=\"https://github.com/BerriAI/litellm\"),\n            ),\n            litellm_debug_info=extra_information,\n        )\n    elif \"API key not valid.\" in error_str:\n        raise AuthenticationError(\n            message=f\"{custom_llm_provider.capitalize()}Exception - {error_str}\",\n            model=model,\n            llm_provider=custom_llm_provider,\n            litellm_debug_info=extra_information,\n        )\n    elif \"403\" in error_str:\n        raise BadRequestError(\n            message=f\"{custom_llm_provider.capitalize()}Exception BadRequestError - {error_str}\",\n            model=model,\n            llm_provider=custom_llm_provider,\n            response=httpx.Response(\n                status_code=403,\n                request=httpx.Request(\n                    method=\"POST\",\n                    url=\" https://cloud.google.com/vertex-ai/\",\n                ),\n            ),\n            litellm_debug_info=extra_information,\n        )\n    elif (\n        \"The response was blocked.\" in error_str\n        or \"Output blocked by content filtering policy\" in error_str  # anthropic on vertex ai\n    ):\n        raise ContentPolicyViolationError(\n            message=f\"{custom_llm_provider.capitalize()}Exception ContentPolicyViolationError - {error_str}\",","sourceCodeStart":1113,"sourceCodeEnd":1149,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/litellm_core_utils/exception_mapping_utils.py#L1113-L1149","documentation":"In _map_vertex_exception, if the error string contains '403' (and no earlier rule matched), LiteLLM raises a BadRequestError with a synthetic 403 response. Vertex AI 403 responses mean the caller's credentials are authenticated but not authorized: the principal lacks the Vertex AI Service Agent role, the API is disabled, or the resource lives in another project. Note LiteLLM's historical quirk: despite the 403 status it maps to BadRequestError here rather than PermissionDeniedError (which is only used for a literal status_code == 403 later in the chain).","triggerScenarios":"A vertex_ai completion where the underlying google.cloud exception string contains '403': caller lacks roles/aiplatform.user, the Vertex AI API is disabled on the project, VPC-SC or org policy blocks the endpoint, or the model is not available in the configured region.","commonSituations":"Service account has only Viewer role; using a shared model endpoint in a different GCP project without cross-project service usage permission; regional restriction (model not enabled in vertex_location); org policy / VPC Service Controls perimeter rejection.","solutions":["Grant the calling principal roles/aiplatform.user (or roles/aiplatform.serviceAgent) on the project","Enable aiplatform.googleapis.com in the project that owns the model deployment","Verify the model is supported in vertex_location (e.g. some models only in us-central1/europe-west4) and switch location","Check the raw error text for which permission was denied, and inspect VPC-SC / org-policy constraints if present"],"exampleFix":"# before\nresp = completion(\n    model=\"vertex_ai/gemini-1.5-pro\",\n    messages=[...],\n    vertex_project=\"shared-models-proj\",\n)\n# ...Exception BadRequestError - 403 ... PERMISSION_DENIED\n\n# after: give the SA access in the owning project\n# gcloud projects add-iam-policy-binding shared-models-proj \\\n#   --member='serviceAccount:caller@proj.iam.gserviceaccount.com' \\\n#   --role='roles/aiplatform.user'\nresp = completion(\n    model=\"vertex_ai/gemini-1.5-pro\",\n    messages=[...],\n    vertex_project=\"shared-models-proj\",\n    vertex_location=\"us-central1\",\n)","handlingStrategy":"try-catch","validationCode":"import subprocess\n\ndef has_aiplatform_role(project: str, member: str) -> bool:\n    out = subprocess.run(\n        [\"gcloud\", \"projects\", \"get-iam-policy\", project, \"--flatten\",\n         \"bindings[].members\", \"--filter\", f\"bindings.members:{member}\",\n         \"--format\", \"value(bindings.role)\"],\n        capture_output=True, text=True,\n    )\n    return \"roles/aiplatform.user\" in out.stdout","typeGuard":null,"tryCatchPattern":"import litellm\n\ntry:\n    resp = litellm.completion(model=\"vertex_ai/gemini-1.5-pro\", messages=msgs)\nexcept litellm.BadRequestError as e:\n    if \"403\" in str(e):\n        raise PermissionError(\n            \"Vertex 403: check roles/aiplatform.user, API enabled, region\"\n        ) from e\n    raise","preventionTips":["Codify IAM grants (terraform/gcloud) so every deploy target gets roles/aiplatform.user","Run a pre-flight permission check job in CI against each target project","Pin vertex_location to a region that serves your models"],"tags":["litellm","vertex-ai","permissions","iam","http-403"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}