Skip to content

OAuth refresh token lost during token refresh, causing 'No refresh token is set' after ~1 hour #21691

Description

@nbardy

Problem

When Google OAuth refreshes an access token, the tokens event payload only contains the new access_token — it does not resend the refresh_token. However, both OAuthCredentialStorage.saveCredentials() and the file-based cacheCredentials() overwrite the stored credentials entirely, wiping out the existing refresh token.

This causes sessions to fail with API Error: No refresh token is set after the first access token expiry (~1 hour).

Additionally

deleteCredentials() in both FileTokenStorage and KeychainTokenStorage throws an error when the credential doesn't exist (e.g., was already deleted). This causes a cascading "Failed to clear OAuth credentials" error loop when re-auth tries to clear credentials that are already gone, preventing users from re-authenticating.

Steps to reproduce

  1. Authenticate with Google OAuth
  2. Use the CLI for >1 hour (until access token expires)
  3. Send another message → No refresh token is set
  4. CLI attempts to clear credentials and re-auth → repeated "Failed to clear OAuth credentials" errors

Expected behavior

  • Refresh tokens should be preserved when saving a token refresh (merge with existing rather than overwrite)
  • Deleting non-existent credentials should be a no-op

Environment

  • macOS, using GEMINI_FORCE_ENCRYPTED_FILE_STORAGE=true
  • Affects both encrypted (OAuthCredentialStorage) and file-based (cacheCredentials) storage paths

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area/coreIssues related to User Interface, OS Support, Core Functionalityeffort/small1 day or less: trivial logic, UI adjustments, docshelp wantedWe will accept PRs from all issues marked as "help wanted". Thanks for your support!kind/bugpriority/p1Important and should be addressed in the near term.status/bot-triaged

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions