{"record":{"id":"111c92aa78b5b8e8","repo":"gitbutlerapp/gitbutler","slug":"valid-commit-that-can-be-parsed-todo-allow-it-t","errorCode":null,"errorMessage":"valid commit that can be parsed: TODO - allow it to return errors?","messagePattern":"valid commit that can be parsed: TODO - allow it to return errors\\?","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/gitbutler-commit/src/commit_ext.rs","lineNumber":31,"sourceCode":"    /// Obtain the commit-message as bytes, but without assuming any encoding.\n    fn message_bstr(&self) -> &BStr;\n}\n\nimpl CommitExt for gix::Commit<'_> {\n    fn change_id(&self) -> Option<ChangeId> {\n        let commit = self.decode().ok()?;\n        Headers::try_from_commit_headers(|| commit.extra_headers())?.change_id\n    }\n\n    fn is_conflicted(&self) -> bool {\n        but_core::Commit::try_from(self.clone()).is_ok_and(|commit| commit.is_conflicted())\n    }\n}\n\nimpl CommitMessageBstr for gix::Commit<'_> {\n    fn message_bstr(&self) -> &BStr {\n        self.message_raw()\n            .expect(\"valid commit that can be parsed: TODO - allow it to return errors?\")\n    }\n}\n","sourceCodeStart":13,"sourceCodeEnd":34,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/gitbutler-commit/src/commit_ext.rs#L13-L34","documentation":"CommitMessageBstr::message_bstr() for gix::Commit wraps gix's message_raw(), which returns Result because extracting the message re-validates the decoded commit; the expect asserts a parsed gix::Commit can always yield its raw message, and the message itself flags the gap ('TODO - allow it to return errors?'). It can only fail when the underlying commit object bytes are malformed or corrupted.","triggerScenarios":"Calling message_bstr() wherever but renders commit messages on a commit whose object fails gix's decode step: truncated objects, bit-rot in the ODB, or a hostile repository serving garbage under a valid-looking id.","commonSituations":"Repositories with object-database corruption (failing disks), malicious clones crafted to crash tooling, or partially-completed transfers materializing invalid commit objects.","solutions":["Run `git fsck --full` in the affected repository to locate and repair/re-fetch corrupt objects","On untrusted data, bypass the extension trait: call commit.message_raw()? yourself and propagate the error (see exampleFix)","Change the trait method to return Result so the decode error surfaces instead of a panic (the acknowledged TODO)"],"exampleFix":"// before (caller side)\nlet msg = commit.message_bstr(); // panics inside on undecodable commit\n\n// after\nlet msg = commit\n    .message_raw()\n    .context(\"commit message of undecodable commit object\")?;","handlingStrategy":"try-catch","validationCode":"// Before rendering untrusted commits, check decodability\nif commit.message_raw().is_err() {\n    // skip or quarantine this commit instead of rendering it\n}","typeGuard":"fn commit_message_decodable(commit: &gix::Commit<'_>) -> bool {\n    commit.message_raw().is_ok()\n}","tryCatchPattern":"// Skip the extension trait on untrusted objects; use the fallible API directly\nlet message = commit\n    .message_raw()\n    .context(\"undecodable commit message\")?;","preventionTips":["Prefer commit.message_raw()? over message_bstr() when handling data from untrusted repos","Run git fsck on repositories that feed external tooling","Treat any decode failure as data corruption, not as a control-flow signal"],"tags":["rust","gix","commit","corrupt-object","odb","panic"],"backgroundTag":"malformed-git-object","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}