Hmbown/CodeWhale · error · std::io::Error

(ensure_state_dir error wrapped as io::ErrorKind::NotFound)

Error message

(ensure_state_dir error wrapped as io::ErrorKind::NotFound)

What it means

default_sessions_dir() calls codewhale_config::ensure_state_dir("sessions") to create/locate ~/.codewhale/sessions (including legacy ~/.deepseek migration). If ensure_state_dir fails, the error is rewrapped as io::ErrorKind::NotFound with the underlying message.

Solutions

  1. Ensure HOME is set to an existing, writable directory.
  2. Create ~/.codewhale manually and grant write permission (mkdir -p ~/.codewhale && chmod u+wx ~/.codewhale).
  3. Read the wrapped message (e.to_string()) to see the underlying cause; fix the path/permission it names.

Example fix

// before: HOME unset in container
ENV HOME=/root   # Dockerfile
// after: explicit, writable home
codewhale --home /data/codewhale  # or export CODEWHALE_HOME=/data/codewhale
Defensive patterns

Strategy: fallback

Validate before calling

if std::env::var("HOME").map(|h| h.is_empty()).unwrap_or(true) { eprintln!("HOME is unset; set CODEWHALE_HOME"); }

Try / catch

match default_sessions_dir() {
    Err(e) if e.kind() == io::ErrorKind::NotFound => {
        std::env::set_var("CODEWHALE_HOME", "/tmp/codewhale");
        default_sessions_dir()?
    }
    r => r?,
}

Prevention

When it happens

Trigger: Any API that resolves the default sessions directory when ensure_state_dir cannot create or resolve the state dir — e.g. unwritable or unset HOME, home directory path missing, filesystem permission error.

Common situations: Running in a container or service with HOME unset or read-only; sandboxed environments blocking directory creation; permissions on ~/.codewhale.

Related errors


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

Appendix: source

Thrown at crates/tui/src/session_manager.rs:2899

    let lhs_canonical = fs::canonicalize(lhs).ok();
    let rhs_canonical = fs::canonicalize(rhs).ok();
    match (lhs_canonical, rhs_canonical) {
        (Some(lhs), Some(rhs)) => lhs == rhs,
        _ => lhs == rhs,
    }
}

/// Resolve the default session directory path.
///
/// v0.8.44: prefers `~/.codewhale/sessions`, falls back to
/// `~/.deepseek/sessions` for existing installs. Uses the write-path resolver
/// so the first access relocates any legacy `~/.deepseek/sessions` into
/// `~/.codewhale/sessions` when the primary directory is missing (#3240).
/// If an older build already created an empty primary sessions directory, copy
/// missing legacy entries into it without overwriting newer CodeWhale data.
pub fn default_sessions_dir() -> std::io::Result<PathBuf> {
    let dir = codewhale_config::ensure_state_dir("sessions")
        .map_err(|e| std::io::Error::new(std::io::ErrorKind::NotFound, e.to_string()))?;
    match merge_missing_legacy_session_entries(&dir) {
        Ok(0) => {}
        Ok(count) => {
            tracing::info!(
                target: "session::migration",
                "Copied {count} missing legacy session entries into {}",
                dir.display()
            );
        }
        Err(err) => {
            tracing::warn!(
                target: "session::migration",
                "Could not copy legacy sessions into {}: {err}",
                dir.display()
            );
        }
    }
    Ok(dir)

View on GitHub (pinned to 433685b202)