【Bug已解决】Unable to Use Claude 3.5 Sonet Model on Vertex AI - Error 400: Project Not Allowed 解决方案
一、现象长什么样
你在 Google Cloud 的 Vertex AI 上调用 Claude 3.5 Sonnet(claude-3-5-sonnet),却收到:
Error 400: Project Not Allowed;- 或
PermissionDenied/FAILED_PRECONDITION: Project ... is not allowed to use model ...; - 你的 GCP 项目本身能跑其他 Vertex 模型(如 Gemini),唯独 Claude 不行;
- 有时报的是"模型在该区域不可用",有时是"项目未获授权";
- 你确认 API 已启用、服务账号有权限,但 Claude 仍被拒;
- 用
gcloud ai models list可能根本看不到 Claude 模型。
一句话:Claude 模型在 Vertex AI 上不是"启用 Vertex AI API 就能用",而是需要单独的"模型使用授权"——你的项目还没被批准使用 Claude,于是 400 Project Not Allowed。
二、背景
Vertex AI 是 Google Cloud 的 AI 平台,它提供了部分 Anthropic 模型(Claude 系列)作为"第一方可调用模型"。但 Claude on Vertex 的可用性受两层控制:
- 区域(region)限制:Claude 模型只在特定 Vertex 区域开放(如
us-east5、us-central1等,且随版本变化); - 项目级授权(allowlist):使用 Claude on Vertex 通常需要你的 GCP 项目先通过申请/签约获得使用资格。这不是单纯 IAM 权限,而是 Google 与 Anthropic 合作下的"模型分发授权"。
所以"项目能跑 Gemini"不意味着"项目能跑 Claude"。报Project Not Allowed,几乎就是第二种——授权缺失。
三、根因
根因是项目未被授权在 Vertex AI 上使用 Claude 模型,或请求打到了未开放该模型的区域:
调用 Vertex Claude 模型 -> Vertex 网关校验 (project, region, model) -> 项目不在 Claude 使用 allowlist -> 400 Project Not Allowed -> 或 region 未开放该 Claude 模型 -> 400 / 404这不是代码 bug,而是账号/授权配置问题。任何 SDK 调用(anthropic.AnthropicVertex、或google-cloud-aiplatform的Endpoint.predict)都会得到同样的拒绝,因为拒绝发生在 Google 侧网关,早于你的请求到达模型。
四、最小可运行复现
from dataclasses import dataclass from typing import Dict @dataclass class _VertexGate: allowed_projects: set = None allowed_regions: set = None def __post_init__(self): self.allowed_projects = self.allowed_projects or {"proj-gemini-only"} self.allowed_regions = self.allowed_regions or {"us-central1"} def check(self, project: str, region: str, model: str) -> None: # 模拟 Google 侧网关授权校验 if "claude" in model.lower() and project not in self.allowed_projects: raise PermissionError("400: Project Not Allowed (Claude 未授权)") if region not in self.allowed_regions: raise PermissionError(f"400: region {region} 未开放模型 {model}") def main(): gate = _VertexGate() try: gate.check("proj-gemini-only", "us-central1", "claude-3-5-sonnet") except PermissionError as e: print("ERR:", e) # 400: Project Not Allowed if __name__ == "__main__": main()运行后项目未在 allowlist 时抛Project Not Allowed,与真实表现一致。
五、解决方案(第一层:最小直接修复)
最小修复是为项目申请 Claude on Vertex 的使用授权,并确认区域正确:
- 在 Google Cloud 控制台确认 Vertex AI API 已启用;
- 通过 Anthropic 或 Google Cloud 的合作入口申请 Claude 模型在 Vertex 的使用资格(通常是填表/签约,批准后项目进入 allowlist);
- 调用时使用开放 Claude 的区域(参考官方文档当前支持的区域,例如
us-east5、us-central1等); - 用正确的模型 ID,例如
claude-3-5-sonnet-v2@20241022这类带版本的 ID。
import os from anthropic import AnthropicVertex client = AnthropicVertex( project_id=os.environ["GCP_PROJECT"], region=os.environ["GCP_REGION"], # 必须是开放 Claude 的区域 ) msg = client.messages.create( model="claude-3-5-sonnet-v2@20241022", max_tokens=256, messages=[{"role": "user", "content": "hi"}], )六、解决方案(第二层:结构化改进)
把"Vertex 调用前置校验"抽成策略,在代码侧尽早暴露"授权/区域不对",而不是等 400:
from dataclasses import dataclass, field from typing import Set @dataclass(frozen=True) class ClaudeVertexProjectPolicy: """Vertex AI 调用策略:尽早校验项目授权与区域,避免 400 Project Not Allowed。 规则: - region 必须在开放 Claude 的区域集合内 - project 需在 allowlist(运行前由外部写入配置) - model 使用带版本的官方 ID """ allowed_regions: Set[str] = field(default_factory=lambda: { "us-central1", "us-east5", "europe-west1", }) allowlisted_projects: Set[str] = field(default_factory=set) def precheck(self, project: str, region: str, model: str) -> None: if "claude" in model.lower() and project not in self.allowlisted_projects: raise PermissionError( f"项目 {project} 未获授权在 Vertex 使用 Claude," "请先申请 Claude on Vertex 使用资格" ) if region not in self.allowed_regions: raise PermissionError( f"区域 {region} 未开放 Claude 模型,请用 {sorted(self.allowed_regions)}" ) def pick_model_id(self, base: str, version: str) -> str: return f"{base}@{version}" def demo() -> None: policy = ClaudeVertexProjectPolicy(allowlisted_projects={"proj-ok"}) policy.precheck("proj-ok", "us-central1", "claude-3-5-sonnet") print(policy.pick_model_id("claude-3-5-sonnet-v2", "20241022")) if __name__ == "__main__": demo()把allowlisted_projects从部署配置注入,CI/启动阶段就校验,避免线上才爆 400。
七、解决方案(第三层:断言 / CI 守护)
import pytest from your_module import ClaudeVertexProjectPolicy def test_region_must_be_allowed(): policy = ClaudeVertexProjectPolicy() with pytest.raises(PermissionError): policy.precheck("proj-ok", "asia-east1", "claude-3-5-sonnet") def test_project_must_be_allowlisted(): policy = ClaudeVertexProjectPolicy(allowlisted_projects=set()) with pytest.raises(PermissionError): policy.precheck("proj-x", "us-central1", "claude-3-5-sonnet") def test_allowlisted_passes(): policy = ClaudeVertexProjectPolicy(allowlisted_projects={"proj-ok"}) # 不应抛错 policy.precheck("proj-ok", "us-central1", "claude-3-5-sonnet") def test_model_id_versioned(): policy = ClaudeVertexProjectPolicy() assert policy.pick_model_id("claude-3-5-sonnet-v2", "20241022").endswith("@20241022")CI 里加一条:用gcloud auth后的权限做 dry-run 校验(或读取配置),确保项目/区域/模型 ID 合规。
八、排查清单
- 项目是否单独申请了 Claude on Vertex 的使用授权?这不等于启用 Vertex AI API。
- 调用区域是否开放 Claude?参考官方当前支持区域列表。
- 模型 ID 是否用带版本的官方格式(如
claude-3-5-sonnet-v2@20241022)? - 同一项目能跑 Gemini 但 Claude 报 400,几乎可锁定是授权问题。
- 服务账号 IAM 是否有
Vertex AI User角色? - 是否在代码侧做了 region/project 预校验,避免线上才爆?
九、小结
在 Vertex AI 上调用 Claude 3.5 Sonnet 收到 400 Project Not Allowed,根因不是代码,而是项目尚未获得"Claude on Vertex"的使用授权,或请求打到了未开放该模型的区域。这与能否跑 Gemini 无关——Claude 走单独的 allowlist。最小修复是申请授权、使用开放区域与带版本模型 ID;结构化做法是抽成ClaudeVertexProjectPolicy,在调用前校验项目授权与区域;最后用 pytest 守护区域/授权前置校验,把 400 消灭在请求发出之前。