gemini-cli - 💡(How to fix) Fix deleteCredentials throws when keychain entry doesn't exist, cascading clearCredentials errors [1 comments, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
google-gemini/gemini-cli#25465Fetched 2026-04-16 07:06:06
View on GitHub
Comments
1
Participants
1
Timeline
4
Reactions
0
Author
Participants
Timeline (top)
labeled ×2closed ×1commented ×1

Error Message

KeychainTokenStorage.deleteCredentials() throws Error: No credentials found for <serverName> when the underlying keychainService.deletePassword() returns false (entry not present). Make deleteCredentials idempotent — standard delete semantics. A deletePassword returning false (not-found) should be a no-op, not an error. Same semantics as rm -f, Python dict.pop(k, None), etc. // Idempotent: deleting credentials that don't exist is not an error.

Code Example

async deleteCredentials(serverName: string): Promise<void> {
  const sanitizedName = this.sanitizeServerName(serverName);
  // Idempotent: deleting credentials that don't exist is not an error.
  await this.keychainService.deletePassword(sanitizedName);
}
RAW_BUFFERClick to expand / collapse

Bug

KeychainTokenStorage.deleteCredentials() throws Error: No credentials found for <serverName> when the underlying keychainService.deletePassword() returns false (entry not present).

Impact

During re-auth, clearCredentials (and logout flows) iterate accounts and call deleteCredentials per account. If the keychain has no entry for an account — e.g. when file-fallback was used previously, or after a partial logout — the throw aborts the loop and surfaces as "Failed to clear OAuth credentials" with no way forward. Users end up in a half-auth'd state that's hard to clear without manual intervention.

Proposal

Make deleteCredentials idempotent — standard delete semantics. A deletePassword returning false (not-found) should be a no-op, not an error. Same semantics as rm -f, Python dict.pop(k, None), etc.

Code change is small:

async deleteCredentials(serverName: string): Promise<void> {
  const sanitizedName = this.sanitizeServerName(serverName);
  // Idempotent: deleting credentials that don't exist is not an error.
  await this.keychainService.deletePassword(sanitizedName);
}

Plus a test update so clearAll() succeeds when some accounts are missing.

Related

Fix proposed in #21762 (rebased on current main, keychain-only — FileTokenStorage was removed upstream).

extent analysis

TL;DR

Make deleteCredentials idempotent by not throwing an error when keychainService.deletePassword() returns false, indicating the credential does not exist.

Guidance

  • Review the proposed code change to ensure it aligns with the desired idempotent behavior of deleteCredentials.
  • Update the test suite to include scenarios where some accounts are missing to verify clearAll() succeeds as expected.
  • Consider the impact of this change on other parts of the system that may rely on the previous behavior of deleteCredentials.
  • Evaluate the necessity of adding error handling for cases where keychainService.deletePassword() fails for reasons other than the credential not existing.

Example

The proposed code change is already provided in the issue:

async deleteCredentials(serverName: string): Promise<void> {
  const sanitizedName = this.sanitizeServerName(serverName);
  // Idempotent: deleting credentials that don't exist is not an error.
  await this.keychainService.deletePassword(sanitizedName);
}

This change directly addresses the issue by removing the error throw when the credential is not found.

Notes

This solution assumes that making deleteCredentials idempotent is the correct approach and does not introduce unintended side effects. It's also important to ensure that the test update covers all relevant scenarios to prevent regressions.

Recommendation

Apply the proposed workaround by making deleteCredentials idempotent, as it directly addresses the issue and aligns with standard delete semantics, allowing for a more robust and user-friendly authentication flow.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING