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

  1. Set providerSpecificData.projectId in the Vertex connection settings to your GCP project ID.
  2. 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.
  3. Use a full Service Account JSON key (contains project_id) instead of a bare accessToken.
  4. 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

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


AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30). Data as JSON: /api/errors/551837bb96ed5d48. Report an issue: GitHub.