decolua/9router · error
Vertex: failed to refresh access token from ADC JSON (author
Error message
Vertex: failed to refresh access token from ADC JSON (authorized_user)
What it means
Thrown in VertexExecutor.execute (open-sse/executors/vertex.js:150) when the ADC (Application Default Credentials) authorized_user flow fails: refreshGoogleToken(refresh_token, client_id, client_secret) returned no accessToken. ADC JSON created by `gcloud auth application-default login` holds a long-lived refresh token that is exchanged at Google's OAuth2 token endpoint; a failed exchange yields no Bearer token.
Source
Thrown at open-sse/executors/vertex.js:150
const saJson = parseVertexSaJson(credentials?.apiKey);
const adcJson = parseVertexAdcJson(credentials?.apiKey);
// SA JSON flow: mint Bearer token via JWT assertion (cached)
if (saJson) {
const result = await refreshVertexToken(saJson, log);
if (!result?.accessToken) throw new Error("Vertex: failed to mint access token from Service Account JSON");
credentials.accessToken = result.accessToken;
}
// ADC user credential flow: refresh Bearer token via Google OAuth2 token endpoint
if (adcJson) {
const result = await refreshGoogleToken(
adcJson.refresh_token,
adcJson.client_id,
adcJson.client_secret,
log
);
if (!result?.accessToken) throw new Error("Vertex: failed to refresh access token from ADC JSON (authorized_user)");
credentials.accessToken = result.accessToken;
}
// vertex-partner with raw key: auto-resolve project_id if not provided
if (this.provider === "vertex-partner" && !saJson && !adcJson && !credentials?.providerSpecificData?.projectId) {
const projectId = await resolveProjectId(credentials.apiKey);
if (!projectId) throw new Error("Vertex: could not resolve project_id from API key. Please add it manually in provider settings.");
log?.debug?.("VERTEX", `Resolved project_id: ${projectId}`);
credentials.providerSpecificData = { ...credentials.providerSpecificData, projectId };
}
const url = this.buildUrl(model, stream, 0, credentials);
const headers = this.buildHeaders(credentials, stream);
const transformedBody = this.transformRequest(model, body, stream, credentials);
const response = await proxyAwareFetch(url, {
method: "POST",
headers,View on GitHub (pinned to 90b52e06ff)
Solutions
- Re-run `gcloud auth application-default login` to obtain a fresh refresh_token, then re-save the ADC JSON as the apiKey.
- Run `gcloud auth application-default set-quota-project YOUR_PROJECT_ID` in the same session so the new JSON is complete.
- Verify network/proxy access to https://oauth2.googleapis.com/token.
- If ADC keeps failing, switch to a Service Account JSON key instead (different minting path, not user-token dependent).
Example fix
// before: stale ADC JSON
{ "type": "authorized_user", "refresh_token": "1//old...", ... }
// after: regenerate, then
{ "type": "authorized_user", "refresh_token": "1//new...", "client_id": "...", "client_secret": "...", "quota_project_id": "my-gcp-project" } Defensive patterns
Strategy: retry
Validate before calling
const adc = parseVertexAdcJson(creds?.apiKey);
if (adc) {
const required = ["refresh_token", "client_id", "client_secret"];
const missing = required.filter(k => !adc[k]);
if (missing.length) throw new Error(`ADC JSON missing fields: ${missing.join(", ")}`);
} Type guard
function isValidAdcJson(v) {
if (typeof v !== "string") return false;
try {
const j = JSON.parse(v);
return j.type === "authorized_user" && !!j.refresh_token && !!j.client_id && !!j.client_secret;
} catch { return false; }
} Try / catch
try {
await vertexChat(model, body);
} catch (e) {
if (/failed to refresh access token from ADC JSON/.test(e.message)) {
// refresh token likely revoked — cannot self-heal, force re-login
await gcloudAdcReLoginFlow();
} else throw e;
} Prevention
- Refresh ADC tokens periodically — long-idle refresh tokens can be revoked.
- Avoid running `gcloud auth application-default revoke`; it invalidates the stored token.
- Detect invalid_grant early and prompt re-login instead of retrying endlessly.
- Have a fallback SA-JSON credential path for headless environments.
When it happens
Trigger: credentials.apiKey parses as ADC JSON (type 'authorized_user' with client_id, client_secret, refresh_token) and refreshGoogleToken resolves to null or { accessToken: undefined } — typically because Google rejected the refresh_token (invalid_grant) or the token endpoint was unreachable.
Common situations: The ADC refresh token was revoked (running `gcloud auth application-default revoke`, password change, or >7 days of inactivity for certain scopes); the ADC JSON is stale from a previous machine; client_id/client_secret were edited; corporate proxy blocks oauth2.googleapis.com.
Related errors
- Vertex: failed to mint access token from Service Account JSO
- loadCodeAssist failed: HTTP ${response.status} ${errorText.s
- onboardUser HTTP ${response.status}: ${errorText.slice(0, 20
- No Codex access token available. Please re-authorize the con
- No GitHub access token available. Please re-authorize the co
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/97b98bb96da244e5.
Report an issue: GitHub.