{"record":{"id":"4b02aa4717cf4a2d","repo":"GitoxideLabs/gitoxide","slug":"an-undo-queue-commit-does-not-use-the-empty-tree","errorCode":null,"errorMessage":"an undo queue commit does not use the empty tree","messagePattern":"an undo queue commit does not use the empty tree","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gix-tix/src/edit/undo.rs","lineNumber":839,"sourceCode":"        gix::refs::TargetRef::Symbolic(_) => bail!(\"{name} must be a direct reference\"),\n    }\n}\n\nstruct ParsedCommit {\n    parent: Option<ObjectId>,\n    title: String,\n    changes: Vec<RefChange>,\n}\n\nfn parse_commit(repo: &gix::Repository, id: ObjectId) -> Result<ParsedCommit> {\n    let commit = repo\n        .find_commit(id)\n        .with_context(|| format!(\"could not find undo queue commit {id}\"))?\n        .decode()\n        .context(\"could not decode an undo queue commit\")?\n        .into_owned()\n        .context(\"could not own an undo queue commit\")?;\n    ensure!(\n        commit.tree == ObjectId::empty_tree(repo.object_hash()),\n        \"an undo queue commit does not use the empty tree\"\n    );\n    let message = gix::objs::commit::MessageRef::from_bytes(&commit.message);\n    let title = message\n        .title\n        .to_str()\n        .context(\"an undo operation title is not UTF-8\")?\n        .to_owned();\n    validate_title(&title)?;\n    let body = message.body.context(\"an undo queue commit has no metadata body\")?;\n    let changes = parse_config(repo, body)?;\n    let parent = commit.parents.first().copied();\n    match parent {\n        None => {\n            ensure!(title == START_TITLE, \"the undo sentinel has the wrong title\");\n            ensure!(changes.is_empty(), \"the undo sentinel contains reference changes\");\n        }","sourceCodeStart":821,"sourceCodeEnd":857,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-tix/src/edit/undo.rs#L821-L857","documentation":"Undo queue commits are metadata-only: their tree must be the empty tree since they store reference changes in the commit message body, not in files. `parse_commit` throws this when a commit found on the undo queue has a non-empty tree, meaning it was not created by the undo machinery.","triggerScenarios":"Calling `parse_commit` (via `is_queue_commit` or `load`) with a commit ID that points to a regular content commit whose tree is not `ObjectId::empty_tree(hash)`.","commonSituations":"Pointing the undo queue ref at an ordinary branch tip, mixing normal commits into the undo queue chain, or reusing an existing branch as the undo queue.","solutions":["Ensure the undo queue ref points only at commits created by the undo API (which always use the empty tree)","Reset the queue ref to a fresh sentinel commit created by the library","If the ref was pointed at a normal branch, create a new dedicated branch for the undo queue"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let is_empty_tree = commit.tree == gix_hash::ObjectId::empty_tree(repo.object_hash());","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Dedicate a ref exclusively to undo queue commits","Never point the undo queue at a regular branch","Verify queue commit trees before parsing in defensive code"],"tags":["git","undo","corruption"],"backgroundTag":"invalid-state-transition","analyzedSha":"e73179060badf27222d790981fac3f84c1830a7e","analyzedAt":"2026-09-08T11:26:50.865Z","contentChangedAt":"2026-09-08T11:26:50.865Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}