decolua/9router · error
Vertex OAuth/ADC requires a project_id. Add quota_project_id
Error message
Vertex OAuth/ADC requires a project_id. Add quota_project_id to your ADC JSON or set providerSpecificData.projectId.
What it means
Thrown by VertexExecutor.buildUrl (open-sse/executors/vertex.js:89) when Gemini on Vertex is requested with OAuth-style credentials (SA JSON, ADC authorized_user JSON, or a pre-set accessToken) but no project_id could be determined. OAuth flows must use the project-scoped path /projects/{id}/locations/{loc}/publishers/google/models/... to avoid Google's RESOURCE_PROJECT_INVALID error, so the executor fails fast with an actionable message instead.
Source
Thrown at open-sse/executors/vertex.js:89
const projectId =
saJson?.project_id ||
adcJson?.quota_project_id ||
credentials?.providerSpecificData?.projectId;
if (this.provider === "vertex-partner") {
// Partner models require project_id in path regardless of auth method
if (!projectId) throw new Error("Vertex partner models require a project_id. Add it in providerSpecificData or use Service Account JSON.");
const url = `https://aiplatform.googleapis.com/v1/projects/${projectId}/locations/global/endpoints/openapi/chat/completions`;
return rawKey ? `${url}?key=${rawKey}` : url;
}
// Gemini on Vertex
const action = stream ? "streamGenerateContent" : "generateContent";
if (usesOAuth) {
// SA JSON / ADC / pre-set accessToken: must use project-scoped path to avoid RESOURCE_PROJECT_INVALID
if (!projectId) {
throw new Error(
"Vertex OAuth/ADC requires a project_id. " +
"Add quota_project_id to your ADC JSON or set providerSpecificData.projectId."
);
}
const location = credentials?.providerSpecificData?.location || "us-central1";
let url = `https://aiplatform.googleapis.com/v1/projects/${projectId}/locations/${location}/publishers/google/models/${model}:${action}`;
if (stream) url += "?alt=sse";
return url;
}
// Raw API key: use global publishers endpoint with ?key= param
// ?alt=sse is required for proper SSE streaming (matches every other Gemini executor)
let url = `https://aiplatform.googleapis.com/v1/publishers/google/models/${model}:${action}`;
if (stream) url += "?alt=sse";
if (rawKey) url += stream ? `&key=${rawKey}` : `?key=${rawKey}`;
return url;
}
View on GitHub (pinned to 90b52e06ff)
Solutions
- Set providerSpecificData.projectId in the Vertex connection settings to your GCP project ID.
- For ADC credentials run `gcloud auth application-default set-quota-project YOUR_PROJECT_ID`, then re-save the ADC JSON so quota_project_id is present.
- Use a full Service Account JSON key (contains project_id) instead of a bare accessToken.
- If passing accessToken programmatically, also pass providerSpecificData: { projectId: '...' } in the same credentials object.
Example fix
// before
const creds = { accessToken: token };
// after
const creds = { accessToken: token, providerSpecificData: { projectId: "my-gcp-project", location: "us-central1" } }; Defensive patterns
Strategy: validation
Validate before calling
const sa = parseVertexSaJson(creds?.apiKey);
const adc = parseVertexAdcJson(creds?.apiKey);
const usesOAuth = !!sa || !!adc || !!creds?.accessToken;
const projectId = sa?.project_id || adc?.quota_project_id || creds?.providerSpecificData?.projectId;
if (usesOAuth && !projectId) {
throw new Error("Vertex OAuth credentials need a project_id: set providerSpecificData.projectId or quota_project_id in the ADC JSON");
} Type guard
function hasVertexOAuthProjectId(creds) {
return Boolean(creds?.providerSpecificData?.projectId) || Boolean(parseVertexSaJson(creds?.apiKey)?.project_id) || Boolean(parseVertexAdcJson(creds?.apiKey)?.quota_project_id);
} Try / catch
try {
await chat(model, body);
} catch (e) {
if (/Vertex OAuth\/ADC requires a project_id/.test(e.message)) {
await configureVertexProject(connectionId);
} else throw e;
} Prevention
- After `gcloud auth application-default login`, always run `gcloud auth application-default set-quota-project YOUR_PROJECT`.
- Never pass a bare accessToken without also passing providerSpecificData.projectId.
- Prefer full Service Account JSON over manually minted tokens.
- Validate OAuth credentials include a project_id when saving the connection.
When it happens
Trigger: buildUrl is called with provider 'vertex', usesOAuth true (apiKey parsed as SA JSON, parsed as ADC authorized_user JSON, or credentials.accessToken already set), and all of saJson.project_id, adcJson.quota_project_id, and credentials.providerSpecificData.projectId are falsy.
Common situations: User pasted ADC credentials from `gcloud auth application-default login` on a machine where no quota project was configured; an accessToken was set manually (e.g. from `gcloud auth print-access-token`) without any projectId in providerSpecificData; a service-account JSON from an unusual source omitted project_id.
Related errors
- Vertex partner models require a project_id. Add it in provid
- Vertex: could not resolve project_id from API key. Please ad
- xai discovery ${field} is empty
- Kiro tool input must be a JSON object
- Vertex: failed to mint access token from Service Account JSO
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/551837bb96ed5d48.
Report an issue: GitHub.