{"record":{"id":"96cd994385a76c3c","repo":"decolua/9router","slug":"vertex-could-not-resolve-project-id-from-api-key","errorCode":null,"errorMessage":"Vertex: could not resolve project_id from API key. Please add it manually in provider settings.","messagePattern":"Vertex: could not resolve project_id from API key\\. Please add it manually in provider settings\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"open-sse/executors/vertex.js","lineNumber":157,"sourceCode":"      credentials.accessToken = result.accessToken;\n    }\n\n    // ADC user credential flow: refresh Bearer token via Google OAuth2 token endpoint\n    if (adcJson) {\n      const result = await refreshGoogleToken(\n        adcJson.refresh_token,\n        adcJson.client_id,\n        adcJson.client_secret,\n        log\n      );\n      if (!result?.accessToken) throw new Error(\"Vertex: failed to refresh access token from ADC JSON (authorized_user)\");\n      credentials.accessToken = result.accessToken;\n    }\n\n    // vertex-partner with raw key: auto-resolve project_id if not provided\n    if (this.provider === \"vertex-partner\" && !saJson && !adcJson && !credentials?.providerSpecificData?.projectId) {\n      const projectId = await resolveProjectId(credentials.apiKey);\n      if (!projectId) throw new Error(\"Vertex: could not resolve project_id from API key. Please add it manually in provider settings.\");\n      log?.debug?.(\"VERTEX\", `Resolved project_id: ${projectId}`);\n      credentials.providerSpecificData = { ...credentials.providerSpecificData, projectId };\n    }\n\n    const url = this.buildUrl(model, stream, 0, credentials);\n    const headers = this.buildHeaders(credentials, stream);\n    const transformedBody = this.transformRequest(model, body, stream, credentials);\n\n    const response = await proxyAwareFetch(url, {\n      method: \"POST\",\n      headers,\n      body: JSON.stringify(transformedBody),\n      signal,\n    }, proxyOptions);\n\n    return { response, url, headers, transformedBody };\n  }\n}","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/open-sse/executors/vertex.js#L139-L175","documentation":"Thrown in VertexExecutor.execute (open-sse/executors/vertex.js:157) when a 'vertex-partner' connection uses a raw API key (no SA JSON, no ADC, no providerSpecificData.projectId) and the automatic project-ID resolution fails. resolveProjectId sends a probe request to the Vertex publisher endpoint with the key and parses projects/{id} out of Google's error message; if that extraction finds nothing, execution stops here.","triggerScenarios":"provider is 'vertex-partner', apiKey is a raw key, providerSpecificData.projectId is unset, and the resolveProjectId probe either fails to reach aiplatform.googleapis.com, returns a non-JSON body, or returns an error message that does not contain 'projects/{id}/' (e.g. an auth-quota error shape that omits the project path).","commonSituations":"Express-mode Vertex API key that is invalid/expired, so Google returns a bare credential error without the project path; network egress to aiplatform.googleapis.com blocked; a proxy returns an HTML error page; key valid but the probe response shape changed.","solutions":["Manually set projectId in the Vertex partner provider's settings (providerSpecificData.projectId) — this is exactly what the error message asks for and skips auto-resolution entirely.","Verify the API key is valid (try a curl to the Vertex endpoint with ?key=...) — invalid keys won't yield a parseable project path.","Check network/proxy access to https://aiplatform.googleapis.com; the probe must get a JSON error body containing projects/{id}.","Alternatively switch to a Service Account JSON credential, which carries project_id natively."],"exampleFix":"// before\n{ \"apiKey\": \"AQ.Ab8R...\" }\n// after\n{ \"apiKey\": \"AQ.Ab8R...\", \"providerSpecificData\": { \"projectId\": \"my-gcp-project\" } }","handlingStrategy":"validation","validationCode":"if (provider === \"vertex-partner\" && !parseVertexSaJson(creds?.apiKey) && !parseVertexAdcJson(creds?.apiKey) && !creds?.providerSpecificData?.projectId) {\n  console.warn(\"vertex-partner: no projectId — auto-resolution may fail; set providerSpecificData.projectId\");\n}","typeGuard":"function canResolveVertexPartnerProject(creds) {\n  return Boolean(parseVertexSaJson(creds?.apiKey) || parseVertexAdcJson(creds?.apiKey) || (typeof creds?.providerSpecificData?.projectId === \"string\" && creds.providerSpecificData.projectId.trim()));\n}","tryCatchPattern":"try {\n  await chat(model, body);\n} catch (e) {\n  if (/could not resolve project_id from API key/.test(e.message)) {\n    showProjectIdSettingsPrompt();\n  } else throw e;\n}","preventionTips":["Set projectId explicitly in provider settings instead of relying on the probe.","Verify the raw API key works before saving it (a dead key defeats auto-resolution).","Ensure outbound access to aiplatform.googleapis.com so the probe can return a parseable error.","Remember projectId resolution results are cached per key — fix the key, not just the setting, if you rely on auto-resolution."],"tags":["config","vertex-ai","project-id","auto-resolution","api-key"],"backgroundTag":"missing-required-config-field","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}