{"record":{"id":"65e972122daaa4c6","repo":"BloopAI/vibe-kanban","slug":"execution-process-serialization-should-not-fail","errorCode":null,"errorMessage":"Execution process serialization should not fail","messagePattern":"Execution process serialization should not fail","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/services/src/services/events/patches.rs","lineNumber":30,"sourceCode":"/// Helper functions for creating execution process-specific patches\npub mod execution_process_patch {\n    use super::*;\n\n    fn execution_process_path(process_id: Uuid) -> String {\n        format!(\n            \"/execution_processes/{}\",\n            escape_pointer_segment(&process_id.to_string())\n        )\n    }\n\n    /// Create patch for adding a new execution process\n    pub fn add(process: &ExecutionProcess) -> Patch {\n        Patch(vec![PatchOperation::Add(AddOperation {\n            path: execution_process_path(process.id)\n                .try_into()\n                .expect(\"Execution process path should be valid\"),\n            value: serde_json::to_value(process)\n                .expect(\"Execution process serialization should not fail\"),\n        })])\n    }\n\n    /// Create patch for updating an existing execution process\n    pub fn replace(process: &ExecutionProcess) -> Patch {\n        Patch(vec![PatchOperation::Replace(ReplaceOperation {\n            path: execution_process_path(process.id)\n                .try_into()\n                .expect(\"Execution process path should be valid\"),\n            value: serde_json::to_value(process)\n                .expect(\"Execution process serialization should not fail\"),\n        })])\n    }\n\n    /// Create patch for removing an execution process\n    pub fn remove(process_id: Uuid) -> Patch {\n        Patch(vec![PatchOperation::Remove(RemoveOperation {\n            path: execution_process_path(process_id)","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/BloopAI/vibe-kanban/blob/4deb7eca8f381f7cbc1f9d15515a9ab8f8009053/crates/services/src/services/events/patches.rs#L12-L48","documentation":"Panic raised by `Patch::add` when `serde_json::to_value(process)` fails to serialize an `ExecutionProcess`. Serde JSON serialization of a plain data struct cannot fail (no maps with non-string keys, no IO), so the library treats failure as an impossible invariant and panics via expect.","triggerScenarios":"Calling `execution_process_patch::add(&process)` where the ExecutionProcess model contains a serde serializer that errors — e.g. a custom `#[serde(serialize_with)]` returning Err, a field serialized to a Map with non-string keys, or a poisoned/failed serialization adapter introduced by schema changes.","commonSituations":"Adding a custom Serialize impl or serde_with attribute to ExecutionProcess that can fail; upgrading serde_json and relying on an error path that previously never ran; generating the struct's TS/serde derives from a macro emitting an invalid serializer.","solutions":["Inspect ExecutionProcess (crates/db/src/models/execution_process.rs) for custom serialize_with/serde_with attributes or manual Serialize impls that can return Err; remove or fix them.","Ensure no field serializes into a serde_json::Value::Object with non-string keys (e.g. HashMap<i64, _>).","If failure must be tolerated, replace the expect with a match on to_value and return a Result or fall back to Value::Null.","Run `cargo test -p db` round-trip tests (serialize then deserialize an ExecutionProcess) to catch the failing field."],"exampleFix":"// before\nvalue: serde_json::to_value(process).expect(\"Execution process serialization should not fail\"),\n// after\nvalue: serde_json::to_value(process).unwrap_or(serde_json::Value::Null), // or propagate Result","handlingStrategy":"validation","validationCode":"// Pre-check that the struct round-trips through serde_json:\nlet v = serde_json::to_value(&process).expect(\"probe serialization\");\nlet _back: ExecutionProcess = serde_json::from_value(v).expect(\"round-trip failed\");","typeGuard":"fn is_json_serializable<T: serde::Serialize>(v: &T) -> bool {\n    serde_json::to_value(v).is_ok()\n}","tryCatchPattern":"// Panics are not catchable in normal Rust; validate first or use catch_unwind for belt-and-braces:\nlet result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| execution_process_patch::add(&process)));","preventionTips":["Add a round-trip (to_value + from_value) unit test for ExecutionProcess in CI.","Avoid fallible custom serialize_with on DB model structs; keep them plain data.","Never use map fields with non-string keys in serde-serializable models.","Review serde/serde_json upgrade diffs for behavior changes."],"tags":["panic","serde","serialization","internal-invariant"],"backgroundTag":"serde-serialization-failed","analyzedSha":"4deb7eca8f381f7cbc1f9d15515a9ab8f8009053","analyzedAt":"2026-08-29T09:24:13.446Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}