{"record":{"id":"c1bc0f596e013b9e","repo":"Hmbown/CodeWhale","slug":"error-session-export","errorCode":null,"errorMessage":"{error}","messagePattern":"\\{error\\}","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/session_export.rs","lineNumber":234,"sourceCode":"            // Parent directories and the leaf are opened without following links.\n            // Stream this handle directly; never reopen a validated path.\n            let mut file = WorkspaceFile::open(root, relative, false)?.open_file()?;\n            append_member(\n                &mut tar,\n                name,\n                MemberContents::File(&mut file),\n                &mut summary.members,\n            )?;\n        }\n        let manifest_json = serde_json::to_string_pretty(&ArchiveManifest {\n            archive_format_version: SESSION_ARCHIVE_FORMAT_VERSION,\n            generator: env!(\"CARGO_PKG_NAME\"),\n            generator_version: env!(\"CARGO_PKG_VERSION\"),\n            exported_at: Utc::now().to_rfc3339(),\n            session: session.metadata.clone(),\n            members: summary.members.clone(),\n        })\n        .map_err(|error| io::Error::new(io::ErrorKind::InvalidData, error))?;\n        append_member(\n            &mut tar,\n            ARCHIVE_MANIFEST_MEMBER,\n            MemberContents::Bytes(manifest_json.as_bytes()),\n            &mut Vec::new(),\n        )?;\n        let encoder = tar.into_inner()?;\n        let file = encoder.finish()?;\n        file.flush()?;\n        file.sync_all()?;\n    }\n    if options.overwrite {\n        temp.persist(output)\n    } else {\n        temp.persist_noclobber(output)\n    }\n    .map_err(|error| {\n        if error.error.kind() == io::ErrorKind::AlreadyExists {","sourceCodeStart":216,"sourceCodeEnd":252,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/session_export.rs#L216-L252","documentation":"Serializing the archive manifest JSON failed, and the error was converted into an io::Error with InvalidData. The manifest embeds the session metadata and tar member list; serialization only fails if the data cannot be represented as JSON (rare) or the serializer errors mid-write.","triggerScenarios":"Calling write_session_archive (crates/tui/src/session_export.rs:234) when serde_json serialization of the ArchiveManifest returns Err — e.g. session metadata containing non-serializable values or a map with non-string keys introduced by a format change.","commonSituations":"Session metadata produced by a different version with incompatible field types; hand-edited or corrupted metadata loaded into SavedSession; custom Serialize impl that errors.","solutions":["Check the embedded {error} text for the serialization failure detail.","Re-export after regenerating the session metadata with the current app version.","If a custom field type fails to serialize, fix its Serialize implementation or drop it from the manifest."],"exampleFix":"// before: non-string map keys in metadata\ntags: HashMap<i64, String>\n// after\ntags: BTreeMap<String, String>","handlingStrategy":"try-catch","validationCode":"serde_json::to_value(&session.metadata).map_err(|e| format!(\"metadata not serializable: {e}\"))?;","typeGuard":null,"tryCatchPattern":"match write_session_archive(&s, dir, out, o) { Err(e) if e.kind() == io::ErrorKind::InvalidData => eprintln!(\"manifest serialization failed: {e}; regenerate session metadata\"), r => r?, }","preventionTips":["Keep session metadata fields JSON-serializable (string-keyed maps, plain types)","Test archive round-trips after changing SessionMetadata's schema","Migrate old session records to the current format before export"],"tags":["session","export","json","serialization"],"backgroundTag":"json-serialization-failed","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}