{"record":{"id":"5d6cd399b122e99a","repo":"gitbutlerapp/gitbutler","slug":"change-to-discard-at-rela-path-didn-t-have-a-last-known","errorCode":null,"errorMessage":"Change to discard at '{rela_path}' didn't have a last-known tracked state - this is a bug","messagePattern":"Change to discard at '(.+?)' didn't have a last-known tracked state - this is a bug","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-workspace/src/tree_manipulation/discard_worktree_changes.rs","lineNumber":225,"sourceCode":"        /// Assume the resource to be restored doesn't exist as it was deleted.\n        Deleted,\n        /// A similar resource is in its place that needs to be updated.\n        Update,\n    }\n\n    /// Restore `state` by writing it into the worktree of `repo`, possibly re-adding or updating the\n    /// `index` with it so that it matches the worktree.\n    pub fn restore_state_to_worktree(\n        pipeline: &mut gix::filter::Pipeline<'_>,\n        index: &mut gix::index::State,\n        rela_path: &BStr,\n        state: ChangeState,\n        mode: RestoreMode,\n        path_check: &mut gix::status::plumbing::SymlinkCheck,\n        num_sorted_entries: &mut usize,\n    ) -> anyhow::Result<()> {\n        if state.id.is_null() {\n            bail!(\n                \"Change to discard at '{rela_path}' didn't have a last-known tracked state - this is a bug\"\n            );\n        }\n\n        let mut update_index = |md| -> anyhow::Result<()> {\n            crate::commit_engine::index::upsert_index_entry(\n                index,\n                rela_path,\n                Some(&md),\n                state.id,\n                state.kind.into(),\n                gix::index::entry::Flags::UPDATE,\n                num_sorted_entries,\n            )?;\n            Ok(())\n        };\n\n        let repo = pipeline.repo;","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-workspace/src/tree_manipulation/discard_worktree_changes.rs#L207-L243","documentation":"Thrown by hunk::restore_state_to_worktree when the ChangeState handed in has a null (all-zero) OID, meaning there is no known prior tracked blob to restore the file to. The library considers reaching this state a caller-side bug because changes that reach hunk restoration should always carry a resolved previous object id.","triggerScenarios":"Calling restore_state_to_worktree with a previous_state whose id was never resolved from the index/HEAD (null hash), e.g. constructing ChangeState manually, or passing an Addition's state (no prior blob) into the hunk-restore path.","commonSituations":"Custom tooling that builds change descriptors without resolving OIDs, or a bug where an Addition is misclassified as a Modification before hunk restoration.","solutions":["Resolve previous_state.id from the index or HEAD tree before calling; never pass a null OID.","Check state.id.is_null() upstream and route such changes to whole-file or 'delete file' handling instead.","If this arises from library-internal classification, report it as a bug with the reproduction."],"exampleFix":"// before\nhunk::restore_state_to_worktree(wt_change, state, ...)?;\n\n// after\nanyhow::ensure!(!state.id.is_null(), \"no previous state for {}\", wt_change.path);\nhunk::restore_state_to_worktree(wt_change, state, ...)?;","handlingStrategy":"validation","validationCode":"fn has_previous_state(state: &ChangeState) -> bool {\n    !state.id.is_null()\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always resolve previous_state OIDs from the index/HEAD before hunk restoration","Never construct ChangeState manually without resolving the blob id","Classify additions separately so they never reach the hunk-restore path"],"tags":["git","invariant","null-oid"],"backgroundTag":"internal-invariant-violation","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}