{"record":{"id":"db760d5b76ba5802","repo":"CherryHQ/cherry-studio","slug":"vertexai-requires-iam-gcp-auth-configuration","errorCode":null,"errorMessage":"VertexAI requires iam-gcp auth configuration.","messagePattern":"VertexAI requires iam-gcp auth configuration\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/ai/provider/config.ts","lineNumber":591,"sourceCode":"      credentialReceipt: { attribution: 'auth', method: 'iam-aws' }\n    }\n  }\n\n  // API-key fallback. Region undefined so the SDK picks its own default, not a hardcode.\n  const selected = selectApiKey(ctx)\n  return {\n    config: { ...base, providerSettings: { ...selected.baseConfig, baseURL } },\n    credentialReceipt: selected.apiKeySelection\n  }\n}\n\nfunction buildVertexConfig(\n  ctx: BuilderContext\n): ProviderConfig<'google-vertex'> | ProviderConfig<'google-vertex-maas'> {\n  const authConfig = providerService.getAuthConfig(ctx.actualProvider.id)\n\n  if (authConfig?.type !== 'iam-gcp') {\n    throw new Error('VertexAI requires iam-gcp auth configuration.')\n  }\n\n  const { project, location, credentials } = authConfig\n  const googleCredentials = credentials as Record<string, string> | undefined\n\n  const { privateKey, clientEmail } = normalizeVertexCredentials(googleCredentials)\n  const creds = googleCredentials\n    ? { ...googleCredentials, clientEmail, privateKey: formatPrivateKey(privateKey ?? '') }\n    : undefined\n\n  const modelId = ctx.model.apiModelId ?? ctx.model.id\n  const isAnthropic = ctx.aiSdkProviderId === 'google-vertex-anthropic' || modelId.startsWith('claude')\n\n  // MaaS open/partner models (Llama, DeepSeek, Qwen, GLM, Kimi, gpt-oss) are served over\n  // Vertex's OpenAI-compatible Chat Completions endpoint, not the Gemini generateContent\n  // SDK that `google-vertex` uses. They carry a `{publisher}/{model}` id — the model listing\n  // bakes the publisher prefix in (§listModels/vertex), and that same id is the `model` the\n  // OpenAI-compatible endpoint expects. Route them to the dedicated MaaS adapter, which mints","sourceCodeStart":573,"sourceCodeEnd":609,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/src/main/ai/provider/config.ts#L573-L609","documentation":"Provider-config build error for `google-vertex` / `google-vertex-maas`. `buildVertexConfig` calls `providerService.getAuthConfig(providerId)` and requires the result's `type` to be exactly `'iam-gcp'`. Anything else — no auth config at all, an `api-key` config, or an incomplete iam-gcp config — throws a plain `Error` (not an McpError). This blocks provider config construction before any request is sent, because VertexAI has no API-key path in this codebase (unlike Bedrock, which has an api-key fallback at line 578).","triggerScenarios":"Selecting a `google-vertex` provider whose auth settings are missing, set to `api-key`, or set to an auth type other than `iam-gcp`; a partially configured iam-gcp record (e.g. only project, no service-account credentials).","commonSituations":"User picked VertexAI but only filled in an API key (which works for Gemini direct but not Vertex); service-account JSON not pasted or malformed; provider record created without auth; auth config cleared during a settings migration.","solutions":["Configure the VertexAI provider with `iam-gcp` auth: a GCP project, location, and service-account credentials (client_email + private_key).","If you only have a Gemini API key, use the `google` provider instead of `google-vertex`.","Verify `providerService.getAuthConfig(providerId)` returns `{ type: 'iam-gcp', project, location, credentials }` before building the config.","Re-paste the service-account JSON and confirm the private key parses (it is normalized via `normalizeVertexCredentials` + `formatPrivateKey`)."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Before building config, assert the auth shape VertexAI requires.\nfunction assertVertexAuth(authConfig: unknown): asserts authConfig is {\n  type: 'iam-gcp'; project: string; location: string; credentials?: Record<string, string>\n} {\n  if (!authConfig || (authConfig as any).type !== 'iam-gcp') {\n    throw new Error('VertexAI requires iam-gcp auth: set type=iam-gcp, project, location, and service-account credentials.')\n  }\n  if (typeof (authConfig as any).project !== 'string' || typeof (authConfig as any).location !== 'string') {\n    throw new Error('iam-gcp auth requires both project and location.')\n  }\n}","typeGuard":"const isIamGcpAuth = (v: unknown): v is { type: 'iam-gcp'; project: string; location: string; credentials?: Record<string, string> } =>\n  typeof v === 'object' && v !== null &&\n  (v as any).type === 'iam-gcp' &&\n  typeof (v as any).project === 'string' &&\n  typeof (v as any).location === 'string'","tryCatchPattern":"const authConfig = providerService.getAuthConfig(providerId)\ntry {\n  assertVertexAuth(authConfig)\n} catch (e) {\n  // e.message === 'VertexAI requires iam-gcp auth configuration.'\n  // guide the user to either configure iam-gcp or switch to the 'google' (API-key) provider\n  throw e\n}","preventionTips":["Configure VertexAI with iam-gcp auth: project, location, and a service-account JSON (client_email + private_key).","If you only have a Gemini API key, use the `google` provider — `google-vertex` has no api-key fallback.","Validate the auth type BEFORE building the provider config so the user gets a guided message, not a thrown Error at request time.","After pasting a service-account JSON, confirm the private key parses (PEM headers) — it is normalized by `normalizeVertexCredentials`/`formatPrivateKey`."],"tags":["provider","vertex-ai","auth","iam-gcp","configuration"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}