{"record":{"id":"073cd92dcce2de4f","repo":"gitbutlerapp/gitbutler","slug":"failed-to-serialize-hunk-header-e","errorCode":null,"errorMessage":"Failed to serialize hunk_header: {e}","messagePattern":"Failed to serialize hunk_header: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-hunk-assignment/src/lib.rs","lineNumber":143,"sourceCode":"                .branch_ref_bytes\n                .map(|b| gix::refs::FullName::try_from(BString::from(b)))\n                .transpose()\n                .map_err(|e| anyhow::anyhow!(\"Failed to parse branch_ref_bytes: {e}\"))?,\n            line_nums_added: None,   // derived data (not persisted)\n            line_nums_removed: None, // derived data (not persisted)\n            diff: None,              // derived data (not persisted)\n        })\n    }\n}\n\nimpl TryFrom<HunkAssignment> for but_db::HunkAssignment {\n    type Error = anyhow::Error;\n    fn try_from(value: HunkAssignment) -> Result<Self, Self::Error> {\n        let header = value\n            .hunk_header\n            .map(|h| {\n                serde_json::to_string(&h)\n                    .map_err(|e| anyhow::anyhow!(\"Failed to serialize hunk_header: {e}\"))\n            })\n            .transpose()?;\n        Ok(but_db::HunkAssignment {\n            id: value.id.map(|id| id.to_string()),\n            hunk_header: header,\n            path: value.path,\n            path_bytes: value.path_bytes.into(),\n            stack_id: None,\n            branch_ref_bytes: value.branch_ref_bytes.map(|r| r.into_inner().into()),\n        })\n    }\n}\n\nimpl From<HunkAssignment> for but_core::DiffSpec {\n    fn from(value: HunkAssignment) -> Self {\n        let hunk_headers = if let Some(header) = value.hunk_header {\n            vec![but_core::HunkHeader {\n                old_start: header.old_start,","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-hunk-assignment/src/lib.rs#L125-L161","documentation":"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.","triggerScenarios":"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.","commonSituations":"Custom/unusual hunk header payloads introduced by upstream parser changes; type changes in HunkHeader that broke JSON serializability.","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"],"exampleFix":"// before\nserde_json::to_string(&h).map_err(|e| anyhow!(\"Failed to serialize hunk_header: {e}\"))?\n// after\nhunk_header.map(|h| h.to_string()) // if plain-text storage is acceptable","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match but_db::HunkAssignment::try_from(assignment) {\n    Ok(row) => store(row),\n    Err(e) if e.to_string().contains(\"serialize hunk_header\") => {\n        log::error!(\"hunk_header not JSON-serializable: {e}\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["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"],"tags":["serialization","json","database"],"backgroundTag":"json-serialization-failed","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"}