{"record":{"id":"c95b3a8cfa4784e6","repo":"Hmbown/CodeWhale","slug":"serde-json-serialization-error-wrapped-as-io-errorkind-c95b3a","errorCode":null,"errorMessage":"(serde_json serialization error wrapped as io::ErrorKind::InvalidData)","messagePattern":"\\(serde_json serialization error wrapped as io::ErrorKind::InvalidData\\)","errorType":"exception","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/tools/truncate.rs","lineNumber":153,"sourceCode":"    payload_path: &Path,\n    session_id: &str,\n    bytes: &[u8],\n) -> io::Result<PathBuf> {\n    if session_id.trim().is_empty() {\n        return Err(io::Error::new(\n            io::ErrorKind::InvalidInput,\n            \"legacy spillover ownership requires a session id\",\n        ));\n    }\n    let ownership = LegacySpilloverOwnership {\n        schema_version: LEGACY_SPILLOVER_OWNER_SCHEMA_VERSION,\n        origin_session: session_id.to_string(),\n        digest: crate::hashing::sha256_hex(bytes),\n        size_bytes: bytes.len().try_into().unwrap_or(u64::MAX),\n    };\n    let sidecar = legacy_spillover_ownership_path(payload_path);\n    let encoded = serde_json::to_vec_pretty(&ownership)\n        .map_err(|error| io::Error::new(io::ErrorKind::InvalidData, error))?;\n    crate::utils::write_atomic(&sidecar, &encoded)?;\n    Ok(sidecar)\n}\n\npub(crate) fn read_legacy_spillover_ownership(\n    payload_path: &Path,\n) -> io::Result<LegacySpilloverOwnership> {\n    let sidecar = legacy_spillover_ownership_path(payload_path);\n    if std::fs::symlink_metadata(&sidecar)?\n        .file_type()\n        .is_symlink()\n    {\n        return Err(io::Error::new(\n            io::ErrorKind::PermissionDenied,\n            \"legacy spillover ownership sidecar must not be a symlink\",\n        ));\n    }\n    let ownership = serde_json::from_slice::<LegacySpilloverOwnership>(&std::fs::read(sidecar)?)","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/tui/src/tools/truncate.rs#L135-L171","documentation":"While publishing the legacy spillover ownership sidecar, the LegacySpilloverOwnership struct is serialized to pretty JSON via serde_json::to_vec_pretty. If serialization fails, the error is wrapped as io::ErrorKind::InvalidData. This is rare for plain structs but possible (e.g. a map key or value type that serde cannot serialize), and it aborts the ownership write before anything is placed on disk.","triggerScenarios":"Calling publish_legacy_spillover_ownership where serde_json::to_vec_pretty(&ownership) fails — practically only when the struct contains non-serializable data (NaN floats, non-string map keys) or a poisoned custom serializer; the standard fields here make this an internal-invariant style failure.","commonSituations":"A modified LegacySpilloverOwnership struct gained a field whose type fails serialization at runtime; serde feature flags changed; corrupted in-memory digest/size data.","solutions":["Read the wrapped serde message to see which field failed to serialize.","Verify LegacySpilloverOwnership fields are all plainly serializable types (strings, u64) after recent changes.","Confirm serde_json is built with standard features and no custom serializers are in play.","If it persists, capture the error in a unit test with the exact bytes/struct to pin down the failing field."],"exampleFix":"// before\nlet encoded = serde_json::to_vec_pretty(&ownership)\n    .map_err(|error| io::Error::new(io::ErrorKind::InvalidData, error))?;\n// after (diagnostic)\nlet encoded = serde_json::to_vec_pretty(&ownership).unwrap_or_else(|error| {\n    panic!(\"spillover ownership serialization failed: {error}\") // invariant: plain struct\n});","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match publish_legacy_spillover_ownership(&path, &sid, &bytes) {\n    Err(e) if e.kind() == std::io::ErrorKind::InvalidData => eprintln!(\"serialization failed: {e}\"),\n    other => other?,\n}","preventionTips":["Keep LegacySpilloverOwnership fields to plainly serializable types","Add a unit test serializing the struct after any field change","Do not override serde behavior with custom serializers for this type"],"tags":["serde","json","serialization","io","spillover"],"backgroundTag":"json-serialization-failed","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-22T06:17:15.046Z"}