sinelaw/fresh · error · io::Error (NotFound)

home directory not found

Error message

home directory not found

What it means

The Filesystem trait's home_dir() fails when dirs::home_dir() returns None, i.e. the user's home directory cannot be determined. Local filesystems read $HOME, remote filesystems resolve the remote home; either may be unavailable. Many path expansions (~) depend on this.

Solutions

  1. Set HOME in the environment before running the editor.
  2. For services, specify Environment=HOME=/home/user in the unit or wrapper script.
  3. If a remote filesystem, verify the remote session resolves a home directory.
Defensive patterns

Strategy: try-catch

Validate before calling

if std::env::var("HOME").map(|h| h.is_empty()).unwrap_or(true) {
    eprintln!("HOME is unset; ~ expansion will fail");
}

Try / catch

match fs.home_dir() {
    Ok(home) => home,
    Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
        PathBuf::from(std::env::var("HOME").unwrap_or_else(|_| "/tmp".into()))
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling home_dir() on a local filesystem with $HOME unset (and no passwd entry), or on a remote filesystem whose session has no home.

Common situations: Commands run from cron/systemd with a minimal environment; containers running as a user without /etc/passwd entry.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of sinelaw/fresh@67894ca546 (2026-09-13). Data as JSON: /api/errors/1255704c56f3ea80. Report an issue: GitHub.

Appendix: source

Thrown at crates/fresh-editor-core/src/model/filesystem.rs:688

    fn remote_channel_id(&self) -> Option<u64> {
        None
    }

    /// A handle notified once per successful transport hot-swap of the backing
    /// agent channel. `None` for local filesystems. The editor awaits this to
    /// drive event-driven reconnect handling (respawning embedded terminals)
    /// instead of polling `is_remote_connected()`.
    fn remote_reconnect_notify(&self) -> Option<std::sync::Arc<tokio::sync::Notify>> {
        None
    }

    /// Get the home directory for this filesystem
    ///
    /// For local filesystems, returns the local home directory.
    /// For remote filesystems, returns the remote home directory.
    fn home_dir(&self) -> io::Result<PathBuf> {
        dirs::home_dir()
            .ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "home directory not found"))
    }

    // ========================================================================
    // Search Operations
    // ========================================================================

    /// Search a file on disk for a pattern, returning one batch of matches.
    ///
    /// Call repeatedly with the same cursor until `cursor.done` is true.
    /// Each call searches one chunk; the cursor tracks position and line
    /// numbers across calls.
    ///
    /// The search runs where the data lives: `StdFileSystem` reads and
    /// scans locally; `RemoteFileSystem` sends a stateless RPC to the
    /// remote agent.  Only matches cross the network.
    ///
    /// For searching an already-open buffer with unsaved edits, use
    /// `TextBuffer::search_scan_all` which reads from the piece tree.

View on GitHub (pinned to 67894ca546)