[BUG] Reftable repos: CLI reads .git/HEAD directly, branch resolves to ".invalid" and PR status is dropped from the statusLine payload

Status Open
Reported on v2.1.267
Maintainer reply None cached
Activity 1 comment · opened Sep 22, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

In a repo using git's reftable ref backend (extensions.refStorage = reftable), Claude Code's CLI resolves the current branch by reading .git/HEAD directly. Under reftable that file is a deliberate stub containing ref: refs/heads/.invalid, so the CLI picks up the sentinel verbatim.

This has a consequence that hasn't been reported before: the pr field is silently omitted from the statusLine JSON payload, so any status line that renders PR number/review state shows nothing — even with an open, non-draft PR on the branch and the GitHub integration otherwise working. The server-side PR poller appears to key its lookup on the branch name, searches for a PR on .invalid, and finds none.

Two other symptoms appear in the same session-start context block, both consistent with raw ref-file reads:

Current branch: .invalid
Main branch (you will usually use this for PRs): main

Current branch is the .git/HEAD stub. Main branch is wrong too — the repo's actual main branch is master. Under reftable,
.git/refs/heads is a file (containing this repositot), not a directory, so enumerating it finds no branchesand detection falls back to main.

Note this differs from #64858, where only the current-branch line was file-derived and Main branch was correct. On the CLI both lines are wrong.

What Should Happen?

Branch should resolve through git, which handles every ref backend correctly:

  • git symbolic-ref --quiet --short HEAD (empty when detached → fall back to git rev-parse --short HEAD), or
  • parse the # branch.head line of git status --porcelain=v2 --branch

Branch enumeration should likewise use git branch / git for-each-ref rather than listing .git/refs/heads/.

With the branch resolving correctly, the PR poller should find the open PR and populate pr in the statusLine payload.

Error Messages/Logs

No error is emitted — this is a silent incorrect value, so nothing appears in crash/error logs. The only signal is the self-contradicting context block quoted above.

Steps to Reproduce

# 1. Create a repo on the reftable backend
git init --ref-format=reftable /tmp/reftable-pr-repro
cd /tmp/reftable-pr-repro
git commit --allow-empty -m init
git switch -c feature/xyz

# 2. Confirm the stubs vs. what git actually reports
cat .git/HEAD                      # -> ref: refs/heads/.invalid   (stub)
file .git/refs/heads               # -> ASCII text (a FILE, not a directory)
cat .git/refs/heads                # -> this repository uses the reftable format
git symbolic-ref --short HEAD      # -> feature/xyz   (git is correct)
git branch --show-current          # -> feature/xyz
  1. Push the branch to a GitHub remote and open a PR against it.
  2. Start Claude Code in the repo with a status line that renders pr.number / pr.review_state.
  3. Observe: session-start context reports Current branch: .invalid; the PR segment never renders because pr is absent from the statusLine payload.

Claude Model

None

Is this a regression?

No, this never worked

Last Working Version

_No response_

Claude Code Version

2.1.267

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

iTerm2

Additional Information

Ruled out as causes (verified on the affected machine):

| Hypothesis | Result |
|---|---|
| git too old to understand reftable | No — both 2.55.0 (Homebrew) and 2.54.0 (Apple Git-157) resolve the branch correctly via git -C <repo> rev-parse --abbrev-ref HEAD |
| GitHub App / gh auth broken | No — gh auth status clean; gh pr view returns the open, non-draft PR |
| Something specific to this machine or repo | No — two sibling repos on the same machine using refstorage=files show correct branch detection and a working PR segment. Only the reftable repo is affected |

Relationship to existing issues

  • #64858 — same root cause, but scoped to the desktop launcher branch chip (labeled area:ui / area:desktop). Closed as completed 2026-08-25. The CLI path is still affected on 2.1.267, which postdates that fix.
  • #68236 — the CLI gitStatus twin of this bug. Auto-closed as inactive by the stale bot without triage, and now locked, so it can't be reopened or commented on. Filing fresh rather than duplicating.

Neither covers the statusLine pr omission, which is the user-visible impact here.

Local stopgap (not a fix — git re-stamps the file on the next checkout):

printf 'ref: refs/heads/<branch>\n' > .git/HEAD

Or convert the clone off reftable (ref storage is local-only, not replicated by push/fetch):

git refs migrate --ref-format=files --dry-run
git refs migrate --ref-format=files

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗