gitbutlerapp/gitbutler · error
Failed to serialize hunk_header
Error message
Failed to serialize hunk_header: {e} What it means
When persisting a HunkAssignment back to the database, the optional hunk_header must be JSON-serialized into the row's text column. If serde_json::to_string fails (should be rare for serializable header structs), try_from aborts with this error.
Solutions
- Inspect the HunkHeader contents that fail to serialize (non-JSON-serializable fields)
- Fix the HunkHeader type so all fields are JSON-serializable (e.g. use String keys in maps)
- Fallback: store the header via Display instead of JSON if it is plain text
Example fix
// before
serde_json::to_string(&h).map_err(|e| anyhow!("Failed to serialize hunk_header: {e}"))?
// after
hunk_header.map(|h| h.to_string()) // if plain-text storage is acceptable Defensive patterns
Strategy: try-catch
Try / catch
match but_db::HunkAssignment::try_from(assignment) {
Ok(row) => store(row),
Err(e) if e.to_string().contains("serialize hunk_header") => {
log::error!("hunk_header not JSON-serializable: {e}");
}
Err(e) => return Err(e),
} Prevention
- Keep HunkHeader types trivially JSON-serializable (string keys, no arbitrary maps)
- Add a round-trip serialize/deserialize test for HunkAssignment
- Avoid embedding non-serializable or untyped data in hunk headers
When it happens
Trigger: TryFrom<HunkAssignment> for but_db::HunkAssignment where value.hunk_header is Some(h) and serde_json::to_string(&h) fails — e.g. header contains a map with non-string keys or a type that cannot serialize to JSON.
Common situations: Custom/unusual hunk header payloads introduced by upstream parser changes; type changes in HunkHeader that broke JSON serializability.
Understand the failure class
Background: "JSON serialization failed", "not JSON serializable", "Failed to serialize": why JSON marshaling errors happen and how to fix them — this error's family across 46 libraries.
Related errors
- Invalid Handler value
- assignments_error: assignments_error.clone()…
- assignments_error.map(|err| serde_error::Error::new(&*err))
- BUG: Sensitive data cannot be serialized - it needs to be…
- Could not open projects file at
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/073cd92dcce2de4f.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but-hunk-assignment/src/lib.rs:143
.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 {
id: value.id.map(|id| id.to_string()),
hunk_header: header,
path: value.path,
path_bytes: value.path_bytes.into(),
stack_id: None,
branch_ref_bytes: value.branch_ref_bytes.map(|r| r.into_inner().into()),
})
}
}
impl From<HunkAssignment> for but_core::DiffSpec {
fn from(value: HunkAssignment) -> Self {
let hunk_headers = if let Some(header) = value.hunk_header {
vec![but_core::HunkHeader {
old_start: header.old_start,View on GitHub (pinned to 58e5313667)