Hmbown/CodeWhale · error · io::Error (AlreadyExists)

already exists; pass --force to overwrite it

Error message

{} already exists; pass --force to overwrite it

What it means

When `force` is not set, the archive is persisted with `persist_noclobber`, which fails if the output file already exists. The library maps that AlreadyExists error into a clearer message telling you to pass `--force` (or set the force option) to overwrite. Nothing was written; the existing file is untouched.

Solutions

  1. Set `force: true` in SessionArchiveOptions (or pass `--force` on the CLI) to overwrite the existing file.
  2. Delete or rename the existing output file before exporting.
  3. Generate a unique output name (e.g. include a timestamp or session id) so collisions cannot occur.
  4. Check `Path::exists()` first and branch on the user's intent.

Example fix

// before
write_session_archive(&session, dir, &out, options)?; // fails if out exists
// after
let mut options = options;
options.force = true;
write_session_archive(&session, dir, &out, options)?;
Defensive patterns

Strategy: validation

Validate before calling

if out.exists() && !opts.force {
    return Err(format!("{} exists; re-run with --force", out.display()).into());
}

Try / catch

match write_session_archive(&session, dir, out, opts) {
    Err(e) if e.kind() == io::ErrorKind::AlreadyExists => {
        eprintln!("{} exists; pass --force", out.display());
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling `write_session_archive` with `options.force == false` (the default) while `output` already exists on disk — e.g. re-running an export to the same filename.

Common situations: Re-running a scripted export that overwrote nothing the second time; a leftover archive from a previous run with the same timestamp/name; CI reusing a workspace without cleaning artifacts.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/66eb1ed432d54b8f. Report an issue: GitHub.

Appendix: source

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

        append_member(
            &mut tar,
            ARCHIVE_MANIFEST_MEMBER,
            MemberContents::Bytes(manifest_json.as_bytes()),
            &mut Vec::new(),
        )?;
        let encoder = tar.into_inner()?;
        let file = encoder.finish()?;
        file.flush()?;
        file.sync_all()?;
    }
    if options.overwrite {
        temp.persist(output)
    } else {
        temp.persist_noclobber(output)
    }
    .map_err(|error| {
        if error.error.kind() == io::ErrorKind::AlreadyExists {
            io::Error::new(
                io::ErrorKind::AlreadyExists,
                format!(
                    "{} already exists; pass --force to overwrite it",
                    output.display()
                ),
            )
        } else {
            error.error
        }
    })?;

    Ok(summary)
}

/// Directory holding this session's artifacts, when it exists. `session_id`
/// is re-checked against path traversal here because this helper is also the
/// boundary for callers that build the path from user-supplied ids.
pub fn session_artifacts_dir(sessions_dir: &Path, session_id: &str) -> io::Result<Option<PathBuf>> {

View on GitHub (pinned to 433685b202)