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

  1. Re-run `gcloud auth application-default login` to obtain a fresh refresh_token, then re-save the ADC JSON as the apiKey.
  2. Run `gcloud auth application-default set-quota-project YOUR_PROJECT_ID` in the same session so the new JSON is complete.
  3. Verify network/proxy access to https://oauth2.googleapis.com/token.
  4. 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

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


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