{"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":400,"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/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/litellm_core_utils/exception_mapping_utils.py#L1113-L1149","documentation":"The error string from the Vertex call contains '403' and litellm maps it to BadRequestError (message '<Provider>Exception BadRequestError - <error_str>' with a synthetic 403 response). A 403 from Vertex means the authenticated identity lacks IAM permission on the project or the model is not enabled for the project. Note this string-based branch runs before the status-code branches, so a 403 surfaces as BadRequestError here, not PermissionDeniedError.","triggerScenarios":"Service account missing roles/aiplatform.user; VPC Service Controls perimeter blocking the API; Model Garden models (e.g. Anthropic on Vertex) used without explicit enablement/agreement; cross-project model access without a grant — and the 403 surfaces in the error body text.","commonSituations":"Newly created service account with no roles bound; org policy or VPC-SC denying egress; teams assuming Claude-on-Vertex works out of the box.","solutions":["Grant the caller access: gcloud projects add-iam-policy-binding <proj> --member=serviceAccount:<sa> --role=roles/aiplatform.user","For Model Garden / Anthropic models, complete the enablement and terms flow in the Google Cloud console first","Verify VPC Service Controls permits access from your network to the Vertex API","Test with user credentials (gcloud auth application-default login) to distinguish IAM problems from network denials"],"exampleFix":"# before\nlitellm.completion(\n    model='vertex_ai/claude-3-5-sonnet',\n    messages=messages,\n)  # 403: model not enabled / SA lacks role\n\n# after\n# 1) gcloud projects add-iam-policy-binding my-proj \\\n#      --member=serviceAccount:runner@my-proj.iam.gserviceaccount.com \\\n#      --role=roles/aiplatform.user\n# 2) enable Claude in Model Garden (console: Vertex AI -> Model Garden -> Enable)\nlitellm.completion(\n    model='vertex_ai/claude-3-5-sonnet@20240620',\n    messages=messages,\n    vertex_project='my-proj',\n    vertex_location='us-east5',\n)","handlingStrategy":"try-catch","validationCode":"from googleapiclient import discovery\n\ndef sa_has_aiplatform_role(project_id: str, sa_email: str, creds) -> bool:\n    crm = discovery.build('cloudresourcemanager', 'v1', credentials=creds)\n    policy = crm.projects().getIamPolicy(resource=project_id).execute()\n    for binding in policy.get('bindings', []):\n        if 'roles/aiplatform.user' in binding['role'] and f'serviceAccount:{sa_email}' in binding['members']:\n            return True\n    return False","typeGuard":"import litellm\n\ndef is_vertex_403_string(exc: BaseException) -> bool:\n    return isinstance(exc, litellm.exceptions.BadRequestError) and '403' in str(exc)","tryCatchPattern":"import litellm\nfrom litellm.exceptions import BadRequestError\n\ntry:\n    resp = litellm.completion(model='vertex_ai/claude-3-5-sonnet', messages=messages)\nexcept BadRequestError as e:\n    if '403' in str(e):\n        # IAM/enablement problem surfaced via error text: fix grants, do not retry\n        raise RuntimeError('vertex 403: grant roles/aiplatform.user and enable the model')\n    raise","preventionTips":["Bind roles/aiplatform.user to every service account at project bootstrap","Complete Model Garden enablement (terms acceptance) for each third-party model before use","Add an IAM pre-check (getIamPolicy) to deployment pipelines for Vertex-calling services"],"tags":["vertex-ai","gcp","http-403","iam","permissions","litellm"],"backgroundTag":"permission-denied","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}