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
- Ensure a non-empty, valid id is passed before calling write_spillover
- Verify HOME (or the platform home directory) is set in the execution environment
- Validate/normalize ids at the call site (e.g. reject empty or path-hostile characters)
- 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
- Validate ids at the boundary where they are created, not at write time
- Guarantee HOME is set in service/container environments
- Centralize id generation so empty ids cannot occur
- Unit-test the home-directory-absent path
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
- Codewhale home directory not found
- allowlisted read-only executable
- Ambiguous prefix ' ' matches sessions
- cannot locate the installed dsh package root from
- Cannot open session : its queued input is already open in…
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)