Hmbown/CodeWhale · error · SecretsError::Io
could not resolve home directory for FileKeyringStore
Error message
could not resolve home directory for FileKeyringStore
What it means
FileKeyringStore cannot determine the user's home directory, so it cannot locate its secrets.json backing file. The secrets crate requires a home directory to derive the on-disk keyring store path (`$HOME/secrets/secrets.json`), and throws this NotFound io::Error wrapped in SecretsError when `dirs::home_dir()` (or equivalent) returns None.
Solutions
- Set the HOME environment variable to a writable directory the user owns (e.g. `export HOME=/home/user` or `Environment=HOME=/var/lib/service` in systemd).
- Ensure the user has a valid passwd entry with a home path (check `getent passwd $(whoami)`).
- In containers, create the home directory and pass it via `-e HOME=/home/app` and a mounted/created volume.
- If programmatic, use the store API that accepts an explicit root/path instead of relying on home resolution.
Example fix
// before (Dockerfile) CMD ["codewhale"] // after ENV HOME=/home/app RUN mkdir -p /home/app/secrets && chown -R app:app /home/app CMD ["codewhale"]
Defensive patterns
Strategy: validation
Validate before calling
fn home_is_resolvable() -> bool {
std::env::var_os("HOME").map(|h| !h.is_empty()).unwrap_or(false)
}
if !home_is_resolvable() {
eprintln!("HOME is not set; FileKeyringStore will fail");
} Type guard
fn has_home() -> Option<String> {
std::env::var("HOME").ok().filter(|h| !h.is_empty())
} Try / catch
match store.init() {
Err(SecretsError::Io(e)) if e.kind() == std::io::ErrorKind::NotFound => {
// home unresolvable: fall back to env-provided key or prompt user
}
other => other?,
} Prevention
- Always export HOME in service units, containers, and cron environments.
- Smoke-test home resolution at process startup before touching secrets.
- Run under a user account with a valid passwd home entry.
When it happens
Trigger: Constructing or using FileKeyringStore when the home directory cannot be resolved: `HOME` unset, `dirs::home_dir()` returning None, or running under a service account / sandboxed process with no home configured.
Common situations: Running the binary under systemd with no `$HOME`, inside Docker containers without `HOME` set, CI runners with stripped environments, or setuid/nonstandard users lacking a 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
- approval log has no parent
- Codewhale credentials path must be a directory
- CODEWHALE_HOME / user home is unavailable
- could not resolve session artifact path (missing home…
- fleet alert secret is not configured
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/b9ea7216cae2c64d.
Report an issue: GitHub.
Appendix: source
Thrown at crates/secrets/src/lib.rs:841
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 73e0f67d83)