{"record":{"id":"f10d743145b54110","repo":"google-gemini/gemini-cli","slug":"failed-to-retrieve-adc-access-token","errorCode":null,"errorMessage":"Failed to retrieve ADC access token.","messagePattern":"Failed to retrieve ADC access token\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/agents/auth-provider/google-credentials-provider.ts","lineNumber":134,"sourceCode":"        throw new Error(errorMessage);\n      }\n    }\n\n    // Otherwise, access token\n    try {\n      const client = await this.auth.getClient();\n      const token = await client.getAccessToken();\n\n      if (token.token) {\n        this.cachedToken = token.token;\n        // Use expiry_date from the underlying credentials if available.\n        const creds = client.credentials;\n        if (creds.expiry_date) {\n          this.tokenExpiryTime = creds.expiry_date;\n        }\n        return { Authorization: `Bearer ${token.token}` };\n      }\n      throw new Error('Failed to retrieve ADC access token.');\n    } catch (e) {\n      const errorMessage = `Failed to get ADC access token: ${\n        e instanceof Error ? e.message : String(e)\n      }`;\n      debugLogger.error(errorMessage, e);\n      throw new Error(errorMessage);\n    }\n  }\n\n  override async shouldRetryWithHeaders(\n    _req: RequestInit,\n    res: Response,\n  ): Promise<HttpHeaders | undefined> {\n    if (res.status !== 401 && res.status !== 403) {\n      this.authRetryCount = 0;\n      return undefined;\n    }\n","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/google-gemini/gemini-cli/blob/5024443c7217464a66e98f80d73172a26440bd8f/packages/core/src/agents/auth-provider/google-credentials-provider.ts#L116-L152","documentation":"On the access-token path, getClient + getAccessToken succeeded but returned a falsy token.token. This is unusual: ADC found credentials but could not produce a bearer token. The message is thrown directly (not wrapped) and is then caught by the surrounding try/catch and re-thrown with the access-token prefix, but this specific string signals an empty token result.","triggerScenarios":"ADC loaded a client whose credentials have no access token (e.g. an external-account config with an expired source token); a metadata server returned an empty body; the credential source was a file that existed but was empty.","commonSituations":"Workload Identity Federation with a broken credential source; an expired or revoked service-account key that still loads but yields no token; metadata server hiccup returning 200 with empty body.","solutions":["Re-run `gcloud auth application-default login` to refresh local ADC.","If using a key file, regenerate the service-account key.","For Workload Identity Federation, verify the credential source token is still valid.","Retry once; transient empty metadata responses do occur."],"exampleFix":"# before - stale ADC yields no token\n$ node app.js   # 'Failed to retrieve ADC access token.'\n\n# after\n$ gcloud auth application-default login\n$ node app.js","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  return await provider.headers();\n} catch (e) {\n  if (/Failed to retrieve ADC access token\\.$/.test((e as Error).message)) {\n    // empty token result - refresh ADC and retry once\n    await refreshAdc();\n    return provider.headers();\n  }\n  throw e;\n}","preventionTips":["Keep ADC fresh; re-login when tokens feel stale.","Validate Workload Identity Federation source tokens.","Retry once on empty token responses."],"tags":["auth","google-credentials","adc","access-token","environment"],"backgroundTag":null,"analyzedSha":"5024443c7217464a66e98f80d73172a26440bd8f","analyzedAt":"2026-08-12T06:01:53.711Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}