gitbutlerapp/gitbutler · error

snapshot additional ref target is null

Error message

snapshot additional ref target is null

What it means

This error is thrown by `snapshot_reference` when an additional reference recorded in a snapshot resolves to a blob whose contents are the all-zero object ID. GitButler stores extra refs (e.g. applied branch heads) inside snapshot trees as blobs containing a hex object id; a null id means the snapshot data is corrupt or was written from a repo that had no valid target. The library refuses to construct a `SnapshotReference` pointing at nothing.

Solutions

  1. Re-run `but oplog restore` on a different (earlier) snapshot entry that has valid ref targets
  2. Inspect the snapshot tree with `git ls-tree` on the oplog snapshot commit and check the blob contents for the affected ref; verify it is a valid 40-char hex sha
  3. Recreate the branch manually from a known commit and take a fresh snapshot instead of restoring the corrupt one
  4. If corruption is widespread, reset the oplog (`but oplog clear`) and continue with a clean history

Example fix

// corrupt blob: 0000000000000000000000000000000000000000
// fix: point the stored ref blob at a real commit
// before: blob data = "0000000000000000000000000000000000000000"
// after:  blob data = "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0"
Defensive patterns

Strategy: validation

Validate before calling

fn valid_snapshot_ref_target(repo: &gix::Repository, entry: &gix::tree::Entry) -> bool {
    repo.find_blob(entry.id()).ok()
        .and_then(|b| gix::ObjectId::from_hex(&b.data).ok())
        .map(|id| !id.is_null())
        .unwrap_or(false)
}

Prevention

When it happens

Trigger: Restoring an oplog snapshot (`restore_snapshot` -> `snapshot_reference`) where a stored additional-ref blob contains hex '0000000000000000000000000000000000000000' (40 zeros).

Common situations: Corrupted or hand-edited snapshot data in `.git/gitbutler/` refs; snapshots produced by an older/buggy GitButler version that wrote zero ids; interrupted snapshot writes; manual git plumbing experiments that zeroed ref blobs.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/62ef047982a37cb9. Report an issue: GitHub.

Appendix: source

Thrown at crates/gitbutler-oplog/src/oplog.rs:568

) -> Result<Option<SnapshotReference>> {
    let Some(name_entry) = snapshot_tree.lookup_entry_by_path("additional-ref/name")? else {
        return Ok(None);
    };
    let name_blob = repo.find_blob(name_entry.id())?;
    let ref_name = gix::refs::FullName::try_from(name_blob.data.as_bstr())
        .context("snapshot additional ref is invalid")?;
    if ref_name.category() != Some(gix::refs::Category::LocalBranch) {
        bail!("snapshot additional ref is not a local branch");
    }
    let target = snapshot_tree
        .lookup_entry_by_path("additional-ref/target")?
        .map(|entry| {
            let blob = repo.find_blob(entry.id())?;
            gix::ObjectId::from_hex(&blob.data).context("snapshot additional ref target is invalid")
        })
        .transpose()?;
    if target.is_some_and(|target| target.is_null()) {
        bail!("snapshot additional ref target is null");
    }
    Ok(Some(SnapshotReference { ref_name, target }))
}

fn snapshot_checkout(
    snapshot_tree: &gix::Tree<'_>,
    repo: &gix::Repository,
) -> Result<Option<SnapshotCheckout>> {
    let Some(ref_entry) = snapshot_tree.lookup_entry_by_path("checkout/ref")? else {
        return Ok(None);
    };
    let commit_entry = snapshot_tree
        .lookup_entry_by_path("checkout/commit")?
        .context("snapshot checkout ref has no commit")?;
    let ref_blob = repo
        .find_blob(ref_entry.id())
        .context("failed to read snapshot checkout ref")?;
    let ref_name = gix::refs::FullName::try_from(ref_blob.data.as_bstr())

View on GitHub (pinned to 58e5313667)