{"record":{"id":"2a63e9474b31254c","repo":"Hmbown/CodeWhale","slug":"invalid-session-artifact-path","errorCode":null,"errorMessage":"invalid session artifact path","messagePattern":"invalid session artifact path","errorType":"validation","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/artifacts.rs","lineNumber":164,"sourceCode":"        })?;\n    if let Some(parent) = absolute_path.parent() {\n        std::fs::create_dir_all(parent)?;\n    }\n    crate::utils::write_atomic(&absolute_path, content.as_bytes())?;\n    Ok((absolute_path, relative_path))\n}\n\n/// Publish immutable session-owned bytes without replacing an earlier handle.\n/// A duplicate replay with identical bytes is idempotent; a different payload\n/// for the same relative path fails closed.\npub fn write_session_relative_immutable(\n    session_id: &str,\n    relative_path: &Path,\n    content: &[u8],\n) -> io::Result<PathBuf> {\n    let absolute_path =\n        session_artifact_absolute_path(session_id, relative_path).ok_or_else(|| {\n            io::Error::new(io::ErrorKind::InvalidInput, \"invalid session artifact path\")\n        })?;\n    let destination = open_session_relative(session_id, relative_path, true)?;\n    match destination.publish(content) {\n        Ok(()) => {}\n        Err(err) if err.kind() == io::ErrorKind::AlreadyExists => {\n            use std::io::Read;\n            let mut existing = Vec::new();\n            destination\n                .open_file()?\n                .take(content.len() as u64 + 1)\n                .read_to_end(&mut existing)?;\n            if existing != content {\n                return Err(io::Error::new(\n                    io::ErrorKind::AlreadyExists,\n                    \"immutable artifact handle already contains different bytes\",\n                ));\n            }\n        }","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/artifacts.rs#L146-L182","documentation":"`write_session_relative_immutable` resolves the absolute path for a session-relative artifact path; if resolution fails because the home directory is missing (or the relative path cannot be anchored), it throws this InvalidInput error before opening the destination handle. Immutable artifacts must never overwrite differing content, so the write aborts early rather than guessing a location.","triggerScenarios":"Calling `write_session_relative_immutable` (directly or via `write_session_artifact_immutable`, evidence publication, or `export`) in an environment where `session_artifact_absolute_path` returns None — typically HOME unresolvable — or with a relative_path the resolver rejects.","commonSituations":"Headless service/cron/container runs without HOME set; exporting artifacts after switching users; passing a relative path built outside the artifacts API (e.g. absolute or '..'-containing) that cannot be anchored.","solutions":["Set HOME (or run as a user with a resolvable home) before the process starts.","Build relative paths with the artifact module's own helpers instead of constructing Paths manually.","Verify the relative path contains no absolute or parent components that would break resolution.","In services, pre-create and configure a home directory for the daemon user."],"exampleFix":"// before (container)\nCMD [\"codewhale\",\"export\"]\n\n// after\nENV HOME=/home/app\nRUN mkdir -p /home/app && chown -R app:app /home/app\nCMD [\"codewhale\",\"export\"]","handlingStrategy":"validation","validationCode":"fn immut_write_ready(home_set: bool, rel: &Path) -> bool {\n    home_set && rel.is_relative() && !rel.components().any(|c| matches!(c, std::path::Component::ParentDir))\n}","typeGuard":null,"tryCatchPattern":"match write_session_relative_immutable(session, rel, bytes) {\n    Err(e) if e.kind() == std::io::ErrorKind::InvalidInput && e.to_string().contains(\"invalid session artifact path\") => {\n        // HOME missing or bad relative path: fix env/path, retry\n    }\n    other => other?,\n}","preventionTips":["Ensure HOME is set before running artifact exports in services.","Build relative paths only with the artifacts module helpers.","Reject absolute or '..'-containing paths before calling."],"tags":["filesystem","artifacts","environment","immutability"],"backgroundTag":"missing-env-var","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T10:30:35.592Z"}