{"record":{"id":"9f9441233ae82d1a","repo":"Hmbown/CodeWhale","slug":"serde-json-deserialization-error-wrapped-as-io-errorkind","errorCode":null,"errorMessage":"(serde_json deserialization error wrapped as io::ErrorKind::InvalidData)","messagePattern":"\\(serde_json deserialization error wrapped as io::ErrorKind::InvalidData\\)","errorType":"exception","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/session_manager.rs","lineNumber":2212,"sourceCode":"        }\n        Ok(())\n    }\n\n    fn validated_offline_queue_path(&self, session_id: &str) -> std::io::Result<PathBuf> {\n        let trimmed = self.validated_session_id(session_id)?;\n        Ok(self\n            .checkpoints_dir()\n            .join(format!(\"{trimmed}{OFFLINE_QUEUE_SUFFIX}\")))\n    }\n\n    fn read_offline_queue_file(path: &Path) -> std::io::Result<Option<OfflineQueueState>> {\n        let content = match fs::read_to_string(path) {\n            Ok(content) => content,\n            Err(error) if error.kind() == io::ErrorKind::NotFound => return Ok(None),\n            Err(error) => return Err(error),\n        };\n        let state: OfflineQueueState = serde_json::from_str(&content)\n            .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;\n        if state.schema_version > CURRENT_QUEUE_SCHEMA_VERSION {\n            return Err(std::io::Error::new(\n                std::io::ErrorKind::InvalidData,\n                format!(\n                    \"Offline queue schema v{} is newer than supported v{}\",\n                    state.schema_version, CURRENT_QUEUE_SCHEMA_VERSION\n                ),\n            ));\n        }\n        Ok(Some(state))\n    }\n\n    /// Migrate the pre-per-session global queue (`checkpoints/offline_queue.json`).\n    ///\n    /// It holds user-authored text, so it is adopted only by the session it was\n    /// stamped for, and it is removed only once this session's copy is durably\n    /// written. A queue stamped for someone else — or for nobody — is left\n    /// exactly where it is, still readable, for its owner to claim.","sourceCodeStart":2194,"sourceCodeEnd":2230,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/tui/src/session_manager.rs#L2194-L2230","documentation":"`load_offline_queue_state` reads the parked queue JSON and deserializes it with `serde_json::from_str::<OfflineQueueState>`; a malformed file surfaces as `io::ErrorKind::InvalidData` wrapping the serde error. A missing file is handled separately and yields `Ok(None)`, so this error always means the file exists but is not valid JSON/does not match the struct.","triggerScenarios":"Calling `load_offline_queue_state` for a session whose parked-queue file is truncated, partially written, hand-edited, or has fields of the wrong type/shape.","commonSituations":"A crash mid-write on filesystems without atomic rename guarantees; manual edits to checkpoint files; a queue file written by an incompatible older format missing required fields.","solutions":["Read the wrapped serde message to find the exact field/format mismatch.","Delete the corrupted parked-queue file for that session (queue contents are lost) and let the session recreate it.","Restore the file from backup if the queued input matters.","Avoid hand-editing checkpoint files; let the app write them."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if let Ok(txt) = std::fs::read_to_string(path) {\n    if serde_json::from_str::<serde_json::Value>(&txt).is_err() {\n        eprintln!(\"parked queue file is corrupt; delete or restore it\");\n    }\n}","typeGuard":null,"tryCatchPattern":"match manager.load_offline_queue_state(id) {\n    Err(e) if e.kind() == std::io::ErrorKind::InvalidData => {\n        // corrupt file: back it up, delete, continue without queued input\n    }\n    other => other?,\n}","preventionTips":["Never hand-edit parked queue files.","Ensure writes are atomic (the library uses write_atomic) — avoid copying partial files around.","Back up checkpoint directories before tooling experiments."],"tags":["io","serde","json-deserialization","offline-queue"],"backgroundTag":"json-unmarshal-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"}