{"record":{"id":"f8e8616635f401fb","repo":"gitbutlerapp/gitbutler","slug":"snapshot-checkout-commit-is-null","errorCode":null,"errorMessage":"snapshot checkout commit is null","messagePattern":"snapshot checkout commit is null","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/gitbutler-oplog/src/oplog.rs","lineNumber":548,"sourceCode":"    };\n    let commit_entry = snapshot_tree\n        .lookup_entry_by_path(\"checkout/commit\")?\n        .context(\"snapshot checkout ref has no commit\")?;\n    let ref_blob = repo\n        .find_blob(ref_entry.id())\n        .context(\"failed to read snapshot checkout ref\")?;\n    let ref_name = gix::refs::FullName::try_from(ref_blob.data.as_bstr())\n        .context(\"snapshot checkout ref is invalid\")?;\n    if ref_name.category() != Some(gix::refs::Category::LocalBranch) {\n        bail!(\"snapshot checkout ref is not a local branch\");\n    }\n    let commit_blob = repo\n        .find_blob(commit_entry.id())\n        .context(\"failed to read snapshot checkout commit\")?;\n    let commit_id = gix::ObjectId::from_hex(&commit_blob.data)\n        .context(\"snapshot checkout commit is invalid\")?;\n    if commit_id.is_null() {\n        bail!(\"snapshot checkout commit is null\");\n    }\n    Ok(Some(SnapshotCheckout {\n        ref_name,\n        commit_id,\n    }))\n}\n\nfn snapshot_metadata(\n    snapshot_tree: &gix::Tree<'_>,\n    repo: &gix::Repository,\n) -> Result<(ProjectMeta, VirtualBranches)> {\n    let vb_toml_entry = snapshot_tree\n        .lookup_entry_by_path(\"virtual_branches.toml\")?\n        .context(\"failed to get virtual_branches.toml blob\")?;\n    let vb_toml_blob = repo\n        .find_blob(vb_toml_entry.id())\n        .context(\"failed to convert virtual_branches.toml tree entry to blob\")?;\n    let SnapshotVirtualBranches {","sourceCodeStart":530,"sourceCodeEnd":566,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/gitbutler-oplog/src/oplog.rs#L530-L566","documentation":"The snapshot's `checkout/commit` blob parsed to a valid object id that is the null oid. Restore refuses to check out the null commit, treating the snapshot's checkout record as corrupt or incomplete.","triggerScenarios":"Restoring a snapshot whose checkout commit field is all zeros.","commonSituations":"Truncated or hand-edited snapshot trees; placeholder data written by buggy versions; partially failed snapshot writes.","solutions":["Restore an earlier snapshot entry","Repair the `checkout/commit` field to the intended commit id if the snapshot must be used","Report if the snapshot came from the currently running version"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let commit_id = gix::ObjectId::from_hex(&commit_blob.data)?;\nif commit_id.is_null() {\n    return Err(anyhow::anyhow!(\"snapshot checkout commit is null; refusing\"));\n}","typeGuard":"fn is_usable_commit_id(id: gix::ObjectId) -> bool {\n    !id.is_null()\n}","tryCatchPattern":"match oplog.restore(snapshot_id) {\n    Err(err) if err.to_string().contains(\"checkout commit is null\") => { /* restore an earlier snapshot */ }\n    other => other,\n}","preventionTips":["Refuse to write null oids into snapshot blobs","Exercise restore paths with generated snapshots in CI"],"tags":["rust","gitbutler","oplog","restore","null-oid","checkout"],"backgroundTag":"snapshot-metadata-invalid","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}