Hmbown/CodeWhale · error · io::Error

could not resolve spillover path (empty/invalid id or…

Error message

could not resolve spillover path (empty/invalid id or missing home directory)

What it means

write_spillover resolves the spillover file location from a session/content id via spillover_path. When the id is empty or otherwise invalid, or the user's home directory cannot be determined, spillover_path returns None and this InvalidInput io::Error is thrown before any file is written.

Solutions

  1. Ensure a non-empty, valid id is passed before calling write_spillover
  2. Verify HOME (or the platform home directory) is set in the execution environment
  3. Validate/normalize ids at the call site (e.g. reject empty or path-hostile characters)
  4. Handle the error explicitly where the id's provenance is known instead of letting it bubble

Example fix

// before
write_spillover(session_id, content)?;
// after
if session_id.is_empty() {
    anyhow::bail!("cannot spill over: session id is empty");
}
write_spillover(session_id, content)?;
Defensive patterns

Strategy: validation

Validate before calling

if id.is_empty() {
    anyhow::bail!("spillover id must be non-empty");
}
if std::env::var_os("HOME").is_none() {
    anyhow::bail!("HOME is not set; cannot resolve spillover path");
}

Type guard

fn is_valid_spillover_id(id: &str) -> bool {
    !id.is_empty() && id.chars().all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_')
}

Try / catch

match write_spillover(id, content) {
    Ok(path) => path,
    Err(e) if e.kind() == io::ErrorKind::InvalidInput => {
        eprintln!("bad spillover id {id:?} or missing home dir");
        return;
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling write_spillover with an empty string or an id spillover_path rejects (invalid characters/format); calling in an environment where the home directory cannot be resolved (dirs::home_dir() returns None).

Common situations: A session id that was never initialized (empty variable); running in a container or service context with no HOME set; passing user-controlled input as the id without validating it first.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at crates/tui/src/tools/truncate.rs:235

        return Ok(path);
    }
    if let Some(parent) = path.parent() {
        fs::create_dir_all(parent)?;
    }
    crate::utils::write_atomic(&path, content.as_bytes())?;
    Ok(path)
}

/// Write `content` to the spillover file for `id`. Creates the
/// parent directory if needed. Returns the resolved path on success.
///
/// Atomic via `write` + filesystem rename guarantees from the
/// underlying OS — the file is created at a temp name first and
/// then renamed into place. Failures bubble up as `io::Error` so the
/// caller can decide whether to surface them.
pub fn write_spillover(id: &str, content: &str) -> io::Result<PathBuf> {
    let path = spillover_path(id).ok_or_else(|| {
        io::Error::new(
            io::ErrorKind::InvalidInput,
            "could not resolve spillover path (empty/invalid id or missing home directory)",
        )
    })?;
    if let Some(parent) = path.parent() {
        fs::create_dir_all(parent)?;
    }
    crate::utils::write_atomic(&path, content.as_bytes())?;
    Ok(path)
}

/// Drop spillover files older than `max_age`. Returns the number of
/// files removed. Non-fatal: directory-missing returns 0; per-file
/// errors are logged and skipped. Mirrors
/// [`crate::session_manager::prune_workspace_snapshots`].
pub fn prune_older_than(max_age: Duration) -> io::Result<usize> {
    let Some(root) = spillover_root() else {
        return Ok(0);

View on GitHub (pinned to 73e0f67d83)