Hmbown/CodeWhale · error · SecretsError

could not resolve home directory for FileKeyringStore

Error message

could not resolve home directory for FileKeyringStore

What it means

FileKeyringStore persists API keys in <home>/.codewhale/secrets/secrets.json (or legacy <home>/.deepseek/secrets/secrets.json). Both paths are derived from codewhale_paths::user_home(), which tries HOME, then USERPROFILE, then Windows HOMEDRIVE+HOMEPATH, then the platform dirs::home_dir() resolver. When every source is missing or empty, default_codewhale_secrets_path()/legacy_deepseek_secrets_path() fail with this NotFound io::Error wrapped in SecretsError::Io, so any get/set/delete on the file backend (e.g. storing a provider key) fails before any file I/O happens.

Source

Thrown at crates/secrets/src/lib.rs:677

fn default_codewhale_secrets_path() -> Result<PathBuf, SecretsError> {
    Ok(codewhale_paths::codewhale_home()
        .map_err(|error| {
            SecretsError::Io(std::io::Error::new(std::io::ErrorKind::InvalidInput, error))
        })?
        .ok_or_else(home_resolution_error)?
        .join("secrets")
        .join("secrets.json"))
}

fn legacy_deepseek_secrets_path() -> Result<PathBuf, SecretsError> {
    Ok(codewhale_paths::legacy_deepseek_home()
        .ok_or_else(home_resolution_error)?
        .join("secrets")
        .join("secrets.json"))
}

fn home_resolution_error() -> SecretsError {
    SecretsError::Io(std::io::Error::new(
        std::io::ErrorKind::NotFound,
        "could not resolve home directory for FileKeyringStore",
    ))
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum SecretBackendSelection {
    File,
    System,
    Unknown,
}

/// Secret-store backend selected by configuration for a structural diagnostic.
///
/// This type deliberately describes only configuration and filesystem shape.
/// It never implies that a provider credential exists.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[serde(rename_all = "snake_case")]

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Set HOME to an absolute writable path in the launching environment (export HOME=/root, or -e HOME=/root for docker) and rerun; empty values count as unset
  2. For systemd/cron, add Environment="HOME=/var/lib/codewhale" (and a User=) to the unit/job definition
  3. Set CODEWHALE_HOME=/absolute/path to pin the Codewhale home independently of the user-home resolver
  4. On Windows ensure USERPROFILE (or HOMEDRIVE+HOMEPATH) is present in the environment that spawns the process

Example fix

# before (container/CI: no HOME set)
docker run --rm codewhale codewhale login   # -> could not resolve home directory for FileKeyringStore

# after
docker run --rm -e HOME=/root codewhale codewhale login
Defensive patterns

Strategy: validation

Validate before calling

fn home_resolvable() -> Option<PathBuf> {
    codewhale_paths::user_home()
}

// before touching the secrets store:
let home = home_resolvable().or_else(|| {
    eprintln!("HOME/USERPROFILE not set; set HOME or CODEWHALE_HOME before storing secrets");
    None
})?;

Try / catch

match result {
    Err(SecretsError::Io(ref e)) if e.kind() == io::ErrorKind::NotFound
        && e.to_string().contains("home directory") =>
    {
        eprintln!("No home directory: export HOME=/path (or CODEWHALE_HOME=...) and retry");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Constructing or calling FileKeyringStore (get/set/delete of a secret) in a process whose environment has no usable HOME and no USERPROFILE and whose platform home resolver returns None: docker run without -e HOME, a systemd unit or cron job without Environment="HOME=...", a CI step that scrubs env vars, or HOME exported as an empty/whitespace string (treated as unset by normalize_path_value).

Common situations: Headless containers and CI runners that never set HOME; launching codewhale from a service manager, launcher, or GUI wrapper that strips the environment; Windows processes where USERPROFILE is unset; hermetic test harnesses that remove env vars.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/b9ea7216cae2c64d. Report an issue: GitHub.