Skip to content

snapshot tracking can return stale tree after git add failure #26893

Closed as not planned

Description

@muzzlol

Description

Snapshot tracking can silently reuse an old tree when git add --all fails.
In the repro below, snapshot tracking first captures file.txt as v1. The file is then changed to v2, but adding a nested Git repo with no checked-out commit makes git add --all fail. A later write-tree still returns the old v1 tree hash. If OpenCode treats that as a valid current snapshot, a later restore can overwrite newer disk state with stale content.

This can make undo/redo unsafe because the snapshot hash returned after a failed add does not actually represent the current working tree.

lost a 2 days of work cause of it :(

Plugins

None

OpenCode version

Local dev / 1.14.48

Steps to reproduce

WORK=/tmp/oc-snapshot-repro
SNAP=/tmp/oc-snapshot-repro-snapshot
ERR=/tmp/oc-snapshot-add.err
rm -rf "$WORK" "$SNAP" "$ERR"
mkdir -p "$WORK" "$SNAP"
echo "== 1. Real repo starts at v1 =="
git -C "$WORK" init
printf 'v1\n' > "$WORK/file.txt"
git -C "$WORK" add file.txt
git -C "$WORK" -c user.email=[email protected] -c user.name=repro commit -m init
echo "== 2. Snapshot captures v1 =="
GIT_DIR="$SNAP" GIT_WORK_TREE="$WORK" git init
git --git-dir="$SNAP" --work-tree="$WORK" add --all --sparse -- file.txt
SNAP_V1=$(git --git-dir="$SNAP" --work-tree="$WORK" write-tree)
git --git-dir="$SNAP" show "$SNAP_V1:file.txt"
echo "== 3. Disk changes to v2 =="
printf 'v2\n' > "$WORK/file.txt"
cat "$WORK/file.txt"
echo "== 4. Add a nested git repo with no commit =="
mkdir "$WORK/nested-unborn"
git -C "$WORK/nested-unborn" init
printf 'nested\n' > "$WORK/nested-unborn/file.txt"
echo "== 5. Snapshot add fails =="
git --git-dir="$SNAP" --work-tree="$WORK" add --all --sparse -- . 2>"$ERR"
ADD_CODE=$?
echo "snapshot add exit code: $ADD_CODE"
cat "$ERR"
echo "== 6. write-tree still returns old snapshot =="
SNAP_SUPPOSED_V2=$(git --git-dir="$SNAP" --work-tree="$WORK" write-tree)
echo "SNAP_V1=$SNAP_V1"
echo "SNAP_SUPPOSED_V2=$SNAP_SUPPOSED_V2"
git --git-dir="$SNAP" show "$SNAP_SUPPOSED_V2:file.txt"
echo "== 7. Later disk changes to v3 =="
printf 'v3\n' > "$WORK/file.txt"
cat "$WORK/file.txt"
echo "== 8. Restore snapshot caller thinks is v2 =="
git --git-dir="$SNAP" --work-tree="$WORK" read-tree "$SNAP_SUPPOSED_V2"
git --git-dir="$SNAP" --work-tree="$WORK" checkout-index -a -f
cat "$WORK/file.txt"

Actual result:
git add fails, but write-tree returns the old v1 tree. Restoring that snapshot overwrites disk content back to v1.

Expected result:
OpenCode should not return/use a snapshot after snapshot staging fails. It should fail closed, surface a warning, and avoid recording undo/redo metadata for that response.

Screenshot and/or share link

Image

Operating System

macOS

Terminal

WezTerm

Activity

  1. github-actions commented on Jul 11, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions