{"record":{"id":"b22e6205b7f89366","repo":"Hmbown/CodeWhale","slug":"applypatchpreflight-should-serialize","errorCode":null,"errorMessage":"ApplyPatchPreflight should serialize","messagePattern":"ApplyPatchPreflight should serialize","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/tools/apply_patch.rs","lineNumber":697,"sourceCode":"\n    Ok(ApplyPatchPreflight {\n        files_total: changes.len(),\n        touched_files,\n        hunks_total: 0,\n        creates: Vec::new(),\n        deletes: Vec::new(),\n        path_override: None,\n        header_path_mismatch: None,\n    })\n}\n\nfn apply_patch_result_metadata(\n    preflight: &ApplyPatchPreflight,\n    pending: &[PendingWrite],\n    stats: &PatchStatsExt,\n) -> Value {\n    let mut metadata =\n        serde_json::to_value(preflight).expect(\"ApplyPatchPreflight should serialize\");\n    if let Some(object) = metadata.as_object_mut() {\n        object.insert(\"event\".to_string(), json!(\"apply_patch.preflight\"));\n        object.insert(\n            \"mutation\".to_string(),\n            build_mutation_metadata(pending, &stats.file_summaries),\n        );\n    }\n    metadata\n}\n\n/// Preserve the exact applied before/after diff independently from approval\n/// presentation. The TUI consumes this success-only metadata for its calm\n/// File receipt; the normal model-facing result remains compact JSON.\nfn build_mutation_metadata(pending: &[PendingWrite], summaries: &[FileSummary]) -> Value {\n    let mut matched = HashSet::new();\n    let mut renames = Vec::new();\n\n    for (delete_index, (deleted, delete_summary)) in pending.iter().zip(summaries).enumerate() {","sourceCodeStart":679,"sourceCodeEnd":715,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/tools/apply_patch.rs#L679-L715","documentation":"Panic building audit metadata for `apply_patch`: the `ApplyPatchPreflight` struct (derived `Serialize`) is converted with `serde_json::to_value` to emit the `apply_patch.preflight` event. For a derived struct over plain data this conversion is effectively infallible; it fails only if a field is not JSON-representable — non-string map keys or a non-finite float in a newly added field.","triggerScenarios":"Adding a field to `ApplyPatchPreflight` typed as a non-string-keyed map (`HashMap<u32, _>`, `HashMap<PathBuf, _>`) or carrying `f64::NAN`; the first apply_patch call after that build panics while emitting preflight metadata.","commonSituations":"Schema growth on the preflight struct during patch-tool development; copying types from a binary/TOML config context into the JSON metadata context without adjusting key types.","solutions":["Change the offending field to string-keyed maps (`BTreeMap<String, _>`) or sanitize floats, then rebuild.","Convert the expect to `.context(...)?` so the failure propagates into the patch tool's error path instead of crashing the turn.","Add a unit test that round-trips a populated preflight through `serde_json::to_value`.","Keep the struct JSON-shaped by construction: only String/number/bool/Vec/Option fields and string-keyed maps."],"exampleFix":"// before\nserde_json::to_value(preflight).expect(\"ApplyPatchPreflight should serialize\")\n\n// after: propagate into the tool's error path\nlet mut metadata = serde_json::to_value(preflight)\n    .context(\"serialize ApplyPatchPreflight for audit metadata\")?;","handlingStrategy":"validation","validationCode":"// Prove the preflight serializes before emitting the audit event\nif serde_json::to_value(&preflight).is_err() {\n    return emit_without_preflight_metadata();\n}","typeGuard":"fn json_shaped(v: &serde_json::Value) -> bool {\n    match v {\n        serde_json::Value::Number(n) => n.as_f64().map_or(true, f64::is_finite),\n        serde_json::Value::Array(a) => a.iter().all(json_shaped),\n        serde_json::Value::Object(o) => o.values().all(json_shaped),\n        _ => true,\n    }\n}","tryCatchPattern":null,"preventionTips":["Keep ApplyPatchPreflight fields JSON-shaped: string keys, finite numbers.","Round-trip test the struct through `serde_json::to_value` whenever fields are added."],"tags":["rust","serde-json","apply-patch","audit-metadata","panic","expect"],"backgroundTag":"serde-serialization-failed","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}