{"record":{"id":"ade927cf8a1048f1","repo":"Hmbown/CodeWhale","slug":"invalid-session-id","errorCode":null,"errorMessage":"invalid session id","messagePattern":"invalid session id","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/session_export.rs","lineNumber":147,"sourceCode":"///\n/// `session` is typically loaded with\n/// [`SessionManager::load_session_snapshot`](crate::session_manager::SessionManager::load_session_snapshot)\n/// so the archive reflects the durable record without applying resume-time\n/// repair. `sessions_dir` is the trusted session store root; pass `None` (or clear\n/// [`SessionArchiveOptions::include_artifacts`]) to export the transcript\n/// only.\n///\n/// The archive is streamed to a sibling temporary file and renamed into\n/// place, so a failed export never leaves a truncated archive at `output`.\n/// An existing `output` is replaced only when `options.overwrite` is set.\npub fn write_session_archive(\n    session: &SavedSession,\n    sessions_dir: Option<&Path>,\n    output: &Path,\n    options: SessionArchiveOptions,\n) -> io::Result<SessionArchiveSummary> {\n    if !is_valid_session_id(&session.metadata.id) {\n        return Err(io::Error::new(\n            io::ErrorKind::InvalidInput,\n            \"invalid session id\",\n        ));\n    }\n    if options.compression_level > 9 {\n        return Err(io::Error::new(\n            io::ErrorKind::InvalidInput,\n            format!(\n                \"xz compression level {} is out of range 0-9\",\n                options.compression_level\n            ),\n        ));\n    }\n    let session_json = session_json(session)?;\n    let container_json = container_json(session)?;\n    let parent = output\n        .parent()\n        .filter(|parent| !parent.as_os_str().is_empty())","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/session_export.rs#L129-L165","documentation":"write_session_archive refuses to build a session archive when the session's metadata.id is not a valid session id (checked by is_valid_session_id). Session ids become tar member names / file paths, so an invalid id could escape the archive layout or produce a corrupt archive.","triggerScenarios":"Calling write_session_archive (crates/tui/src/session_export.rs:147) with a SavedSession whose metadata.id contains path separators, is empty, or otherwise fails is_valid_session_id — typically a hand-constructed session record or one imported from an incompatible format.","commonSituations":"Exporting sessions from an older/newer store with a different id format; constructing SavedSession in tests or scripts with an arbitrary id string; corrupted session metadata file.","solutions":["Check the session metadata id; regenerate or repair the session record with a valid id.","Export a different session and re-derive the broken one from its transcript.","If constructing sessions in code, generate ids with the session store's id generator instead of raw strings."],"exampleFix":"// before\nlet session = SavedSession { metadata: SessionMetadata { id: \"../evil\".into(), .. } };\n// after\nlet session = SavedSession { metadata: SessionMetadata { id: SessionId::generate(), .. } };","handlingStrategy":"validation","validationCode":"fn id_ok(id: &str) -> bool { !id.is_empty() && id.chars().all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_') }\nassert!(id_ok(&session.metadata.id), \"invalid session id: {:?}\", session.metadata.id);","typeGuard":"fn valid_session(s: &SavedSession) -> bool { is_valid_session_id(&s.metadata.id) }","tryCatchPattern":"match write_session_archive(&s, dir, out, opts) { Err(e) if e.kind() == io::ErrorKind::InvalidInput && e.to_string() == \"invalid session id\" => skip_and_log(&s.metadata.id), r => r?, }","preventionTips":["Generate session ids with the store's id generator, never arbitrary strings","Validate ids after importing sessions from older formats","Treat corrupt metadata as a signal to rebuild the session record"],"tags":["session","export","validation"],"backgroundTag":"invalid-identifier-format","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T21:17:16.096Z"}