decolua/9router · error
Vertex partner models require a project_id. Add it in provid
Error message
Vertex partner models require a project_id. Add it in providerSpecificData or use Service Account JSON.
What it means
Thrown by VertexExecutor.buildUrl (open-sse/executors/vertex.js:78) when routing to the 'vertex-partner' provider (Llama, Mistral, GLM, DeepSeek, Qwen via Vertex AI's global OpenAI-compatible endpoint). The partner endpoint URL embeds the GCP project ID in the path (/projects/{id}/locations/global/endpoints/openapi/...), and unlike SA JSON or ADC credentials, a raw API key carries no project ID. The executor refuses to build a URL without one rather than sending a request that would fail upstream.
Source
Thrown at open-sse/executors/vertex.js:78
*/
export class VertexExecutor extends BaseExecutor {
constructor(providerId = "vertex") {
super(providerId, PROVIDERS[providerId] || {});
}
buildUrl(model, stream, urlIndex = 0, credentials = null) {
const saJson = parseVertexSaJson(credentials?.apiKey);
const adcJson = parseVertexAdcJson(credentials?.apiKey);
const usesOAuth = !!saJson || !!adcJson || !!credentials?.accessToken;
const rawKey = !usesOAuth ? credentials?.apiKey : null;
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";View on GitHub (pinned to 90b52e06ff)
Solutions
- Open the Vertex partner provider's settings and set providerSpecificData.projectId to your GCP project ID (e.g. 'my-gcp-project').
- Switch the credential to a Service Account JSON key: download the key from GCP IAM (JSON type), ensure it contains project_id, and store it as the apiKey — buildUrl then reads saJson.project_id automatically.
- If using ADC JSON, set quota_project_id in it: run `gcloud auth application-default set-quota-project YOUR_PROJECT_ID` and re-paste the resulting JSON.
- Ensure execute() runs before buildUrl so the raw-key auto-resolution path (resolveProjectId probe) can fill projectId in; a bare buildUrl call with a raw key will always throw.
Example fix
// before (credential JSON)
{ "apiKey": "AQ.Ab8R..." }
// after
{ "apiKey": "AQ.Ab8R...", "providerSpecificData": { "projectId": "my-gcp-project" } } Defensive patterns
Strategy: validation
Validate before calling
const sa = parseVertexSaJson(creds?.apiKey);
const adc = parseVertexAdcJson(creds?.apiKey);
const projectId = sa?.project_id || adc?.quota_project_id || creds?.providerSpecificData?.projectId;
if (provider === "vertex-partner" && !projectId) {
throw new Error("Set providerSpecificData.projectId (or use SA JSON) before calling Vertex partner models");
} Type guard
function hasVertexProjectId(creds) {
const p = creds?.providerSpecificData?.projectId;
return typeof p === "string" && p.trim().length > 0;
} Try / catch
try {
await route(request);
} catch (e) {
if (/Vertex partner models require a project_id/.test(e.message)) {
promptUserToSetProjectId();
} else throw e;
} Prevention
- Always fill providerSpecificData.projectId when saving a Vertex partner connection with a raw API key.
- Prefer Service Account JSON keys — they carry project_id natively.
- Run `gcloud auth application-default set-quota-project` before copying ADC JSON.
- Validate credentials at save time in the UI: warn if projectId is empty for vertex-partner.
When it happens
Trigger: Calling buildUrl (directly or via execute) with provider 'vertex-partner' when projectId resolves to falsy: the apiKey is a raw key (not SA JSON parsed by parseVertexSaJson, not ADC parsed by parseVertexAdcJson), credentials.accessToken is unset, adcJson has no quota_project_id, saJson has no project_id, and credentials.providerSpecificData.projectId is missing/empty. Note: at runtime execute() tries to auto-resolve the project first — this throw from buildUrl alone happens when resolution was skipped or yielded nothing and projectId was never set.
Common situations: User pasted a Vertex express-mode API key into a partner-model connection without filling the projectId field in provider settings; ADC JSON was created by 'gcloud auth application-default login' before a quota project was set (gcloud auth application-default set-quota-project never run); SA JSON downloaded from a service account whose JSON lacks the project_id field; providerSpecificData was reset when the credential was re-imported.
Related errors
- Vertex OAuth/ADC requires a project_id. Add quota_project_id
- Vertex: could not resolve project_id from API key. Please ad
- Vertex: failed to mint access token from Service Account JSO
- Vertex: failed to refresh access token from ADC JSON (author
- Missing base URL
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/aa39ea1eed282f25.
Report an issue: GitHub.