Hmbown/CodeWhale · error

export output must be outside the session store

Error message

export output must be outside the session store

What it means

Before writing the archive, the function canonicalizes the output's parent directory and the sessions store root, and refuses output paths that resolve inside the session store. Writing a tarball into the store could be re-ingested as session data or grow on every export.

Solutions

  1. Choose an output path outside the sessions directory (e.g. ~/exports/session.tar.xz).
  2. If exporting from within the store dir, pass an explicit --output elsewhere.
  3. Resolve symlinks: point the output at a real directory that is not under the store root.

Example fix

// before
cd ~/.codewhale/sessions && codewhale sessions export --output ./backup.tar.xz
// after
codewhale sessions export --output ~/backups/session.tar.xz
Defensive patterns

Strategy: validation

Validate before calling

let root = sessions_dir.canonicalize()?;
let parent = output.parent().unwrap_or(Path::new(".")).canonicalize()?;
assert!(!parent.starts_with(&root), "output must be outside the session store");

Try / catch

match write_session_archive(&s, Some(&store), &out, o) { Err(e) if e.to_string().contains("outside the session store") => eprintln!("move --output outside {}", store.display()), r => r?, }

Prevention

When it happens

Trigger: Calling write_session_archive (crates/tui/src/session_export.rs:172) with an output path whose canonicalized parent is equal to or nested under the canonicalized sessions_dir (including via symlink).

Common situations: Exporting with output defaulting to the current directory while cwd is the sessions directory; symlinked output directory resolving into the store; scripts writing backups next to session data.

Understand the failure class

Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/b8b1231a14f697fc. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/session_export.rs:172

            io::ErrorKind::InvalidInput,
            format!(
                "xz compression level {} is out of range 0-9",
                options.compression_level
            ),
        ));
    }
    let session_json = session_json(session)?;
    let container_json = container_json(session)?;
    let parent = output
        .parent()
        .filter(|parent| !parent.as_os_str().is_empty())
        .map_or_else(|| PathBuf::from("."), Path::to_path_buf);
    fs::create_dir_all(&parent)?;
    let sessions_dir = sessions_dir.map(Path::canonicalize).transpose()?;
    if let Some(root) = &sessions_dir
        && parent.canonicalize()?.starts_with(root)
    {
        return Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            "export output must be outside the session store",
        ));
    }
    let artifact_files = match (options.include_artifacts, sessions_dir.as_deref()) {
        (true, Some(root)) => match session_artifacts_dir(root, &session.metadata.id)? {
            Some(dir) => collect_artifact_files(root, &dir)?,
            None => Vec::new(),
        },
        _ => Vec::new(),
    };
    let mut temp = tempfile::Builder::new()
        .prefix(".codewhale-session-export-")
        .tempfile_in(&parent)?;

    let mut summary = SessionArchiveSummary {
        output: output.to_path_buf(),
        session_id: session.metadata.id.clone(),

View on GitHub (pinned to 73e0f67d83)