{"record":{"id":"5955eab235e8e662","repo":"Hmbown/CodeWhale","slug":"serde-json-serialization-error-wrapped-as-io-errorkind","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/session_manager.rs","lineNumber":2170,"sourceCode":"    pub fn save_offline_queue_state(\n        &self,\n        state: &OfflineQueueState,\n        session_id: Option<&str>,\n    ) -> std::io::Result<PathBuf> {\n        let session_id = session_id.ok_or_else(|| {\n            std::io::Error::new(\n                std::io::ErrorKind::InvalidInput,\n                \"Offline queue cannot be parked without a session id\",\n            )\n        })?;\n        let path = self.validated_offline_queue_path(session_id)?;\n        fs::create_dir_all(self.checkpoints_dir())?;\n        let mut owned = state.clone();\n        // The stamp is redundant with the file name; it stays because the UI's\n        // restore path still compares it against the live session id.\n        owned.session_id = Some(self.validated_session_id(session_id)?.to_string());\n        let content = serde_json::to_string_pretty(&owned)\n            .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;\n        write_atomic(&path, content.as_bytes())?;\n        Ok(path)\n    }\n\n    /// Load one session's parked offline queue if present.\n    pub fn load_offline_queue_state(\n        &self,\n        session_id: &str,\n    ) -> std::io::Result<Option<OfflineQueueState>> {\n        let path = self.validated_offline_queue_path(session_id)?;\n        Ok(match Self::read_offline_queue_file(&path)? {\n            Some(state) => Some(state),\n            None => self.adopt_legacy_offline_queue(session_id, &path)?,\n        })\n    }\n\n    /// Remove one named session's parked offline queue.\n    pub fn clear_offline_queue_state_for(&self, session_id: &str) -> std::io::Result<()> {","sourceCodeStart":2152,"sourceCodeEnd":2188,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/tui/src/session_manager.rs#L2152-L2188","documentation":"In `save_offline_queue_state`, the cloned `OfflineQueueState` is serialized with `serde_json::to_string_pretty` before an atomic write; any serialization failure is wrapped as an `io::ErrorKind::InvalidData` io::Error whose inner error is the serde error. In practice this is rare because the struct is JSON-safe, but a poisoned/invalid custom value or an out-of-range numeric field can trip it.","triggerScenarios":"Calling `save_offline_queue_state` with an `OfflineQueueState` that serde_json cannot serialize (non-string map keys in nested fields, NaN/Infinity floats, invalid values in custom Serialize impls).","commonSituations":"Custom fields added to the queue state containing NaN from computed timings; hand-built state structs populated from untrusted parsing output.","solutions":["Inspect the inner serde error message (`{error}` source) to identify the offending field.","Sanitize numeric fields (no NaN/Infinity) before saving.","Ensure all nested types implement Serialize with string map keys."],"exampleFix":"// before\nstate.retry_at = f64::NAN;\nmanager.save_offline_queue_state(&state, Some(id))?;\n// after\nif state.retry_at.is_finite() {\n    manager.save_offline_queue_state(&state, Some(id))?;\n}","handlingStrategy":"validation","validationCode":"serde_json::to_string_pretty(&state).map_err(|e| e.to_string())?; // dry-run serialize before saving","typeGuard":null,"tryCatchPattern":"match manager.save_offline_queue_state(&state, Some(id)) {\n    Err(e) if e.kind() == std::io::ErrorKind::InvalidData => {\n        eprintln!(\"queue state not serializable: {e}\");\n    }\n    other => other?,\n}","preventionTips":["Keep OfflineQueueState fields finite (no NaN/Infinity) and JSON-safe.","Dry-run serialize custom state before persisting."],"tags":["io","serde","json-serialization","offline-queue"],"backgroundTag":"json-marshal-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"}