gitbutlerapp/gitbutler · error

Failed to parse branch_ref_bytes

Error message

Failed to parse branch_ref_bytes: {e}

What it means

When converting a stored database HunkAssignment row into the domain HunkAssignment, the persisted branch_ref_bytes must be a valid gix::refs::FullName (e.g. refs/heads/...). If parsing fails, the row contains a malformed ref name and the conversion aborts with this error.

Solutions

  1. Fix or clear the malformed branch_ref_bytes value in the HunkAssignment table row
  2. Re-run assignment so rows are rewritten with valid refs
  3. Check for version mismatch between the tool that wrote the DB and the reader; upgrade/downgrade accordingly

Example fix

// before
// row.branch_ref_bytes = "heads/my-branch" (invalid, missing refs/)
// after
// row.branch_ref_bytes = "refs/heads/my-branch"
Defensive patterns

Strategy: try-catch

Validate before calling

if let Some(b) = &row.branch_ref_bytes {
    if gix::refs::FullName::try_from(BString::from(b.clone())).is_err() {
        eprintln!("Skipping row with malformed branch_ref_bytes: {b:?}");
    }
}

Type guard

fn valid_ref(b: &BString) -> Option<gix::refs::FullName> {
    gix::refs::FullName::try_from(b.clone()).ok()
}

Try / catch

match HunkAssignment::try_from(row) {
    Ok(a) => use(a),
    Err(e) if e.to_string().contains("branch_ref_bytes") => {
        log::warn!("corrupt row skipped: {e}");
        // re-assign or repair the row
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: TryFrom<but_db::HunkAssignment> for HunkAssignment encountering branch_ref_bytes that does not parse as a gix::refs::FullName — corrupt or hand-edited DB rows, or rows written by an older version with a different ref format.

Common situations: Schema/version drift after upgrading GitButler; manual DB edits; bugs in earlier writers persisting invalid ref strings.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/956c0590cfc2a356. Report an issue: GitHub.

Appendix: source

Thrown at crates/but-hunk-assignment/src/lib.rs:128

            .hunk_header
            .as_ref()
            .and_then(|h| serde_json::from_str(h).ok());
        let legacy_stack_id = value
            .stack_id
            .as_ref()
            .and_then(|id| uuid::Uuid::parse_str(id).ok())
            .map(StackId::from);
        Ok(HunkAssignment {
            id: value.id.map(|id| Uuid::parse_str(&id)).transpose()?,
            hunk_header: header,
            path: value.path,
            path_bytes: value.path_bytes.into(),
            stack_id: legacy_stack_id,
            branch_ref_bytes: value
                .branch_ref_bytes
                .map(|b| gix::refs::FullName::try_from(BString::from(b)))
                .transpose()
                .map_err(|e| anyhow::anyhow!("Failed to parse branch_ref_bytes: {e}"))?,
            line_nums_added: None,   // derived data (not persisted)
            line_nums_removed: None, // derived data (not persisted)
            diff: None,              // derived data (not persisted)
        })
    }
}

impl TryFrom<HunkAssignment> for but_db::HunkAssignment {
    type Error = anyhow::Error;
    fn try_from(value: HunkAssignment) -> Result<Self, Self::Error> {
        let header = value
            .hunk_header
            .map(|h| {
                serde_json::to_string(&h)
                    .map_err(|e| anyhow::anyhow!("Failed to serialize hunk_header: {e}"))
            })
            .transpose()?;
        Ok(but_db::HunkAssignment {

View on GitHub (pinned to 58e5313667)