google-gemini/gemini-cli · error · Error

Failed to load OAuth credentials

Error message

Failed to load OAuth credentials

What it means

Thrown by OAuthCredentialStorage.loadCredentials() when the underlying HybridTokenStorage fails to read credentials. The method first tries the configured token storage (keychain-backed), then falls back to migrating from the old file-based storage at ~/.gemini/oauth_creds.json. If both paths throw, the error is wrapped with cause and re-thrown. The original error is preserved in the cause chain for diagnostics.

Source

Thrown at packages/core/src/code_assist/oauth-credential-storage.ts:57

          scope: scope || undefined,
        };

        if (expiresAt) {
          googleCreds.expiry_date = expiresAt;
        }

        return googleCreds;
      }

      // Fallback: Try to migrate from old file-based storage
      return await this.migrateFromFileStorage();
    } catch (error: unknown) {
      coreEvents.emitFeedback(
        'error',
        'Failed to load OAuth credentials',
        error,
      );
      throw new Error('Failed to load OAuth credentials', { cause: error });
    }
  }

  /**
   * Save OAuth credentials
   */
  static async saveCredentials(credentials: Credentials): Promise<void> {
    if (!credentials.access_token) {
      throw new Error('Attempted to save credentials without an access token.');
    }

    const existing = await this.storage.getCredentials(MAIN_ACCOUNT_KEY);
    const mergedRefreshToken =
      credentials.refresh_token || existing?.token.refreshToken;

    // Convert Google Credentials to OAuthCredentials format
    const mcpCredentials: OAuthCredentials = {
      serverName: MAIN_ACCOUNT_KEY,

View on GitHub (pinned to 5024443c72)

Solutions

  1. On Linux, ensure gnome-keyring or kwallet is running and DBUS_SESSION_BUS_ADDRESS is exported.
  2. On macOS, unlock the keychain or grant the terminal/IDE access to the 'gemini-cli-oauth' keychain item.
  3. In headless/CI environments, use GEMINI_API_KEY or Application Default Credentials instead of OAuth.
  4. If the stored credentials are corrupt, clear them (OAuthCredentialStorage.clearCredentials()) and re-authenticate.
  5. Inspect error.cause for the underlying storage error to pinpoint keychain vs. file system issues.
Defensive patterns

Strategy: try-catch

Validate before calling

// Check environment suitability before attempting credential load
function hasKeychainAccess(): boolean {
  if (process.platform === 'linux') {
    return !!process.env['DBUS_SESSION_BUS_ADDRESS'];
  }
  return true; // macOS/Windows keychain generally available
}

if (!hasKeychainAccess()) {
  console.warn('No keychain available; set GEMINI_API_KEY for non-interactive auth.');
}

Try / catch

try {
  const creds = await OAuthCredentialStorage.loadCredentials();
} catch (e) {
  if (e instanceof Error && e.message === 'Failed to load OAuth credentials') {
    // Keychain unavailable — fall back to API key or re-auth
    console.error('Credential storage inaccessible. Set GEMINI_API_KEY or re-authenticate.');
    process.exit(1);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling OAuthCredentialStorage.loadCredentials() when storage.getCredentials() throws (e.g., keychain access denied, locked keychain on macOS, or D-Bus/secret-service failure on Linux) AND migrateFromFileStorage() also throws (e.g., the old file is corrupt or unreadable).

Common situations: macOS keychain is locked or the process lacks Keychain access permissions; Linux secret-service (gnome-keyring) is not running or DBUS_SESSION_BUS_ADDRESS is unset; running inside a container or CI without a keyring daemon; the old credentials file exists but is corrupted; permission issues on ~/.gemini directory.

Related errors


AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12). Data as JSON: /api/errors/63c5661fd108f6b8. Report an issue: GitHub.