gitbutlerapp/gitbutler · warning

valid commit that can be parsed: TODO - allow it to return e

Error message

valid commit that can be parsed: TODO - allow it to return errors?

What it means

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.

Source

Thrown at crates/gitbutler-commit/src/commit_ext.rs:31

    /// Obtain the commit-message as bytes, but without assuming any encoding.
    fn message_bstr(&self) -> &BStr;
}

impl CommitExt for gix::Commit<'_> {
    fn change_id(&self) -> Option<ChangeId> {
        let commit = self.decode().ok()?;
        Headers::try_from_commit_headers(|| commit.extra_headers())?.change_id
    }

    fn is_conflicted(&self) -> bool {
        but_core::Commit::try_from(self.clone()).is_ok_and(|commit| commit.is_conflicted())
    }
}

impl CommitMessageBstr for gix::Commit<'_> {
    fn message_bstr(&self) -> &BStr {
        self.message_raw()
            .expect("valid commit that can be parsed: TODO - allow it to return errors?")
    }
}

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Run `git fsck --full` in the affected repository to locate and repair/re-fetch corrupt objects
  2. On untrusted data, bypass the extension trait: call commit.message_raw()? yourself and propagate the error (see exampleFix)
  3. Change the trait method to return Result so the decode error surfaces instead of a panic (the acknowledged TODO)

Example fix

// before (caller side)
let msg = commit.message_bstr(); // panics inside on undecodable commit

// after
let msg = commit
    .message_raw()
    .context("commit message of undecodable commit object")?;
Defensive patterns

Strategy: try-catch

Validate before calling

// Before rendering untrusted commits, check decodability
if commit.message_raw().is_err() {
    // skip or quarantine this commit instead of rendering it
}

Type guard

fn commit_message_decodable(commit: &gix::Commit<'_>) -> bool {
    commit.message_raw().is_ok()
}

Try / catch

// Skip the extension trait on untrusted objects; use the fallible API directly
let message = commit
    .message_raw()
    .context("undecodable commit message")?;

Prevention

When it happens

Trigger: 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.

Common situations: Repositories with object-database corruption (failing disks), malicious clones crafted to crash tooling, or partially-completed transfers materializing invalid commit objects.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/111c92aa78b5b8e8. Report an issue: GitHub.