decolua/9router · warning
[ProjectId] could not fetch projectId for connection
Error message
[ProjectId] could not fetch projectId for connection
What it means
getProjectIdForConnection fetches a Google/Vertex-style projectId for an OAuth connection via fetchProjectId. When the fetch succeeds but returns no projectId, it logs this warning, caches nothing, and returns null so callers treat the connection as having no project ID.
Source
Thrown at open-sse/services/projectId.js:110
return cached.projectId;
}
// Deduplicate concurrent fetches for the same connection
if (pendingFetches.has(connectionId)) {
return pendingFetches.get(connectionId).promise;
}
// Each fetch gets its own AbortController so it can be canceled via removeConnection()
const controller = new AbortController();
const promise = (async () => {
try {
const projectId = await fetchProjectId(accessToken, controller.signal, provider);
if (projectId) {
projectIdCache.set(connectionId, {projectId, fetchedAt: Date.now()});
return projectId;
}
console.warn("[ProjectId] could not fetch projectId for connection", connectionId.slice(0, 8));
return null;
} catch (error) {
console.warn(`[ProjectId] Error fetching project ID: ${error.message}`);
return null;
} finally {
pendingFetches.delete(connectionId);
}
})();
pendingFetches.set(connectionId, {promise, controller, startedAt: Date.now()});
return promise;
}
/**
* Invalidate the cached project ID for a connection.
* Call this when a connection's credentials are fully revoked or refreshed.
*/
export function invalidateProjectId(connectionId) {View on GitHub (pinned to 90b52e06ff)
Solutions
- Log into the provider console and confirm the account has at least one active project
- Re-run the OAuth flow with scopes including project read access
- Check fetchProjectId's parsing against the provider's current API response shape
- Retry after the account/project is provisioned — cache refresh (_refreshProjectId) will pick it up
- If the provider genuinely needs no projectId, treat the null return as expected and skip project-scoped features
Example fix
// before: connection created with minimal scopes scopes: ["userinfo.email"] // after: include project read scope scopes: ["userinfo.email", "cloud-platform"]
Defensive patterns
Strategy: type-guard
Validate before calling
const pid = await getProjectIdForConnection(connectionId);
if (!pid) console.warn('no projectId — skip project-scoped calls'); Type guard
const hasProjectId = (pid) => typeof pid === 'string' && pid.length > 0; if (!hasProjectId(projectId)) return; // skip project-scoped feature
Try / catch
try {
const pid = await getProjectIdForConnection(conn.id);
if (!pid) return null; // function already returns null on failure, never throws
return await projectScopedCall(conn, pid);
} catch (e) {
console.warn(`project-scoped call failed: ${e.message}`);
return null;
} Prevention
- Grant project-read scopes during OAuth consent
- Provision at least one active project on the provider account before connecting
- Treat null projectId as a normal outcome for accounts without projects
- Re-run OAuth if the provider changes its project discovery API
When it happens
Trigger: fetchProjectId returned falsy — the upstream project-listing endpoint returned 200 but with no matching project, the access token lacks permission to list projects, or the provider variant doesn't expose project IDs.
Common situations: OAuth account has no active GCP project; token scopes missing project read permission; provider changed its project discovery API shape so the parser finds nothing; connection created before project setup completed on the provider console.
Related errors
- `Token exchange failed: ${error}`
- Token exchange failed: ${error}
- Failed to get user info: ${error}
- Failed to load code assist: ${errorText}
- Token exchange failed: ${error}
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/e5400d39ddae6220.
Report an issue: GitHub.