Skip to content

Background status fetch triggers a macOS Keychain password prompt through git-credential-osxkeychain and retries it every 15 minutes #13912

Description

@josephv123

What happened

After Homebrew upgraded git, macOS started asking for the login password on behalf of git roughly every 10-15 minutes, usually right after switching back to T3 Code. It was a Keychain prompt; the exact dialog text wasn't captured.

Diagnosis

The prompt comes from the background status fetch (GitVcsDriver.fetchRemoteForStatus) on a project whose origin is a private GitHub repo over HTTPS, with credential.helper=osxkeychain (Homebrew's /opt/homebrew/etc/gitconfig sets this by default).

  1. A saved Keychain item only trusts the app that created it. Homebrew upgraded git to 2.55.0 earlier that day, which replaced git-credential-osxkeychain, so macOS now asks for the login password before releasing the github.com credential. That part is normal macOS behavior.
  2. STATUS_UPSTREAM_REFRESH_ENV sets GCM_INTERACTIVE, GIT_ASKPASS, GIT_TERMINAL_PROMPT, SSH_ASKPASS and SSH_ASKPASS_REQUIRE (from [codex] Make background VCS fetch non-interactive #3133, for [Bug]: Github login popup keep opening multiple times repeatedly in desktop app, UX is getting very bad due to this #2874). None of them affect this dialog, because it comes from the macOS Security framework rather than from git. So a background poll still produces a system password dialog.
  3. The fetch is killed after 5s (STATUS_UPSTREAM_REFRESH_TIMEOUT). That isn't enough time to notice a dialog and type a password, and every attempt on this machine timed out.
  4. Failures back off from 30s up to 15 minutes and never stop, so the prompt keeps coming back. Window focus triggers a refresh ([Bug]: Window focus runs git fetch even with Git fetch interval set to 0 #13235), so it tends to land right when the user returns to the app.

Public repos fetch without credentials, which is why only the private project prompts. A public-repo project on the same machine fetched fine throughout.

Checked against v0.0.42 and current main: the env, the 5s timeout and the 15-minute cap are unchanged. #13812 (--no-auto-gc) doesn't touch this path.

Possible directions: after a few consecutive timeouts, stop polling that remote and show that the background fetch needs attention, instead of retrying forever. Or run background status fetches without credential helpers that can open a GUI.

Steps to reproduce

Derived from this machine's traces and config; not re-run from a clean setup.

  1. On macOS, use Homebrew git with the default credential.helper=osxkeychain.
  2. Clone a private GitHub repo over HTTPS so git saves the token to the login keychain.
  3. brew upgrade git, so git-credential-osxkeychain is replaced by a new binary.
  4. Add the repo as a T3 Code project and open a thread in it.
  5. Switch to another app for more than 15s, then switch back.
  6. macOS asks for the login password on behalf of git-credential-osxkeychain. GitVcsDriver.fetchRemoteForStatus fails with Git command timed out after 5s, and the dialog returns on later refreshes, at most 15 minutes apart.

Version

0.0.42 (desktop app)

Environment

macOS 26.2 (25C56) arm64, desktop app running the server, git 2.55.0 (Homebrew), gh 2.101.0

Evidence

server.trace.ndjson, GitVcsDriver.fetchRemoteForStatus (local time):
  22:43:36  <private-repo>  5007ms  Failure  Git command timed out.
  23:01:12  <private-repo>  5007ms  Failure  Git command timed out.
  23:17:18  <private-repo>  5007ms  Failure  Git command timed out.
  23:44:24  <private-repo>  5008ms  Failure  Git command timed out.
  Same window, <public-repo>: every fetch succeeded in 216-660ms.

Homebrew installed git 2.55.0 at 20:04 the same day. Traces before 22:16
have rotated out, so the first failure isn't captured.

Workaround check, the driver's exact env after `gh auth setup-git`:
  GCM_INTERACTIVE=never GIT_ASKPASS= GIT_TERMINAL_PROMPT=0 SSH_ASKPASS= \
  SSH_ASKPASS_REQUIRE=never git fetch --dry-run --quiet --no-tags origin
  -> exit 0, 0.62s, no dialog

Related issues

#11930 is the same gap in STATUS_UPSTREAM_REFRESH_ENV, but for a GUI SSH agent on the worktree bootstrap fetch. #2874, fixed by #3133, is the Git Credential Manager version; the Keychain helper isn't covered. #13235 explains why the prompt lands on window focus. None of them covers git-credential-osxkeychain or the poller retrying a prompting fetch indefinitely.

Fix applied or workaround

Ran gh auth setup-git, so git gets github.com credentials from gh auth git-credential instead of the Keychain helper. Verified under the driver's env (see Evidence). Alternative: run git fetch once in a terminal and click Always Allow, though that comes back after the next git upgrade.

Filed by

Claude Code (claude-opus-5-5), following .github/triage/PLAYBOOK.md from a T3 Code thread

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    acceptedfeature request acceptedbugSomething is broken or behaving incorrectly.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions