[BUG] Cloud session checks out a stale commit (when the source revision is fully-qualified and an outcome branch is set)

Status Open
Reported on v2.1.247
Maintainer reply None cached
Activity 0 comments · opened Aug 27, 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?

A cloud session created with its source revision written as a fully-qualified ref (refs/heads/<branch>) and an outcome branch naming that same branch is checked out at an older commit than the branch's current head on the remote.

Both HEAD and the remote-tracking ref are left at the older commit, so git status prints Your branch is up to date with 'origin/<branch>'. The session then reads and edits files from a superseded revision with nothing indicating it.

Reflogs from a reproducing session show the fetch retrieved the current head correctly, and the tracking ref was then written backwards:

remote-tracking ref
<older> -> <current> fetch --no-progress --depth 50 origin refs/heads/<branch>: fast-forward
<current> -> <older> (no reflog message)

HEAD
<older> -> <current> (no reflog message)
<current> -> <older> checkout: moving from <current> to <branch>

The local branch ref did not move at all during startup.
This is not a container-reuse or stale-snapshot effect: it reproduced in a newly created cloud environment containing no prior containers, and two sessions on the same container as a reproducing session — differing only in the two creation fields — were checked out at the current head.

Related but distinct: https://github.com/anthropics/claude-code/issues/89868 (stale state after container reclaim). See Additional Information.

What Should Happen?

The session should be checked out at the branch's current head on the remote, which the startup fetch has already retrieved.

Failing that, the remote-tracking ref should be left at the fetched value so the discrepancy is visible — git status should report the branch as behind rather than up to date. Writing the tracking ref backwards to match a stale HEAD makes the condition undetectable without an explicit git ls-remote or git fetch.

Error Messages/Logs

No error is raised. The environment-runner log (/tmp/env-manager.log) from a reproducing session, in order:

Starting repository fetch                                              mode=resume
Fetching specific ref
Git command succeeded                                                  duration_ms=971
Processing branch from outcomes                                        mode=resume
Resume mode: creating local branch directly
Branch doesn't exist on remote, creating new branch locally from current HEAD
Updated remote tracking branch

The branch did exist on the remote: the fetch of that exact ref had just succeeded, and git ls-remote origin <branch> from inside the session returned the current head.

Two timing observations about that sequence:
1. The gap between "Resume mode: creating local branch directly" and "Branch doesn't exist on remote..." is 50 microseconds.
2. No Executing git command entry appears anywhere between "Processing branch from outcomes" and "Updated remote tracking branch".

Resulting state inside the session:

$ git status
On branch <branch>
Your branch is up to date with 'origin/<branch>'.
nothing to commit, working tree clean

$ git rev-parse HEAD
<older-commit>

$ git ls-remote origin <branch>
<current-head>    refs/heads/<branch>

Steps to Reproduce

  1. Push commits to a branch in a repository, so the branch head on the remote is <current-head>.
  2. Create four cloud sessions against that repository and branch, in the same environment, without the remote head changing. Vary only two creation fields:
  • source revision: <branch> (bare name) | outcome branch: not set
  • source revision: <branch> (bare name) | outcome branch: <branch>
  • source revision: refs/heads/<branch> | outcome branch: not set
  • source revision: refs/heads/<branch> | outcome branch: <branch>
  1. In each session run:

git rev-parse HEAD
git status -sb
git ls-remote origin <branch>

Observed: the first three configurations check out <current-head>. Only the fourth — fully-qualified ref plus outcome branch — checks out an older commit while reporting the branch as up to date.

Sessions created through the web UI carry the fully-qualified form together with an outcome branch, which is the fourth configuration. Four such web-created sessions were all checked out at the older commit; a session created with the bare branch name and the same outcome branch, minutes apart against the same remote head, was checked out at the current head.

Workaround: create the session with the bare branch name as the source revision. The outcome branch may still be set to that branch; the session lands on the branch at its current head.

Claude Model

Not sure / Multiple models

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

2.1.247 (Claude Code)

Platform

Anthropic API / Other.
Claude API (claude.ai subscription — Claude Code on the web)

Operating System

Linux (Ubuntu 24.04.4 LTS, kernel 6.18.44-fc-v21, x86_64 — Anthropic-hosted cloud container)

Terminal/Shell

Other. No terminal — Claude Code on the web; container shell is bash.

Additional Information

How the observations were gathered:

  • .git/logs/HEAD, .git/logs/refs/heads/... and .git/logs/refs/remotes/origin/... read inside affected sessions.
  • /tmp/env-manager.log on the container, which records startup for every session that has run on that container.
  • Session records read through the API, for the source-revision and outcome-branch fields as stored.
  • A matrix of sessions created programmatically, varying only those two fields against a fixed repository, branch, environment and remote head.
  • Each configuration was observed once, except the bare-name-with-outcome-branch configuration, which was observed twice and was correct both times.

Relationship to https://github.com/anthropics/claude-code/issues/89868:
That report describes stale working trees after container reclaims during a long-running session, attributed to restoring an out-of-date filesystem snapshot, with untracked files erased and background processes terminated. This report is distinct: it triggers at session creation, depends on two creation fields, flips reliably when either is changed, affects only HEAD and the remote-tracking ref, and loses no data — the fetch retrieves the current objects before the ref is written backwards.

One possible overlap worth checking: a session resuming after a reclaim runs the same branch-processing step (logged mode=resume), so a resumed session configured with an outcome branch may reach the same ref rewrite. That would account for a working tree landing behind commits the same session had previously pushed, without any snapshot being stale — though not for lost untracked files or terminated background processes.

Version mismatch (unrelated to the above):
Ran claude --version here: 2.1.247 (and CLAUDE_CODE_VERSION environment variable in the same session is 2.1.42 — corroborating the mismatch in the other report).

Not established:

  • Where the older commit value originates. In a newly created environment there is no prior local branch and no cached clone, so it does not come from the container.
  • Whether the branch-existence determination consults anything, and if so what. The 50-microsecond gap and the absence of a logged git command are the only observations bearing on it.

Session IDs for the reproducing and control sessions can be supplied on request.

View original on GitHub ↗