ultraworkers/claw-code · error · std::io::Error
HOME is not set (on Windows, set USERPROFILE or HOME, or use
Error message
HOME is not set (on Windows, set USERPROFILE or HOME, or use CLAW_CONFIG_HOME to point directly at the config directory)
What it means
Thrown by credentials_home_dir() in the OAuth credentials layer when neither CLAW_CONFIG_HOME nor HOME nor USERPROFILE is set in the process environment. The runtime needs a directory to place ~/.claw/credentials.json for OAuth tokens, and without any home indicator it cannot construct that path. It surfaces as io::Error with ErrorKind::NotFound, so it can masquerade as a file-not-found error if you only match on kind.
Source
Thrown at rust/crates/runtime/src/oauth.rs:340
error: params.get("error").cloned(),
error_description: params.get("error_description").cloned(),
})
}
fn generate_random_token(bytes: usize) -> io::Result<String> {
let mut buffer = vec![0_u8; bytes];
File::open("/dev/urandom")?.read_exact(&mut buffer)?;
Ok(base64url_encode(&buffer))
}
fn credentials_home_dir() -> io::Result<PathBuf> {
if let Some(path) = std::env::var_os("CLAW_CONFIG_HOME") {
return Ok(PathBuf::from(path));
}
let home = std::env::var_os("HOME")
.or_else(|| std::env::var_os("USERPROFILE"))
.ok_or_else(|| {
io::Error::new(
io::ErrorKind::NotFound,
"HOME is not set (on Windows, set USERPROFILE or HOME, \
or use CLAW_CONFIG_HOME to point directly at the config directory)",
)
})?;
Ok(PathBuf::from(home).join(".claw"))
}
fn read_credentials_root(path: &PathBuf) -> io::Result<Map<String, Value>> {
match fs::read_to_string(path) {
Ok(contents) => {
if contents.trim().is_empty() {
return Ok(Map::new());
}
serde_json::from_str::<Value>(&contents)
.map_err(|error| io::Error::new(io::ErrorKind::InvalidData, error))?
.as_object()
.cloned()View on GitHub (pinned to 08106b0c37)
Solutions
- Set CLAW_CONFIG_HOME to an explicit config directory (this takes priority and bypasses home-dir lookup entirely): export CLAW_CONFIG_HOME=/path/to/config
- Set HOME on Unix: export HOME=/home/user — or USERPROFILE on Windows: set USERPROFILE=C:\Users\user
- If spawning claw from code, pass the env var explicitly: std::process::Command::new("claw").env("HOME", home_dir)
- For Docker, add ENV HOME=/root or ENV CLAW_CONFIG_HOME=/claw-config to the image
- In tests, set CLAW_CONFIG_HOME to a tempfile::tempdir() path instead of mutating HOME (matches the repo's dogfooding convention)
Example fix
// before (fails in container: no HOME, no USERPROFILE) docker run --rm claw-image claw login # after export CLAW_CONFIG_HOME=/tmp/claw-config # or set HOME=/root in the image claw login
Defensive patterns
Strategy: validation
Validate before calling
fn ensure_config_home() -> Result<(), std::io::Error> {
if std::env::var_os("CLAW_CONFIG_HOME").is_some() { return Ok(()); }
let home = std::env::var_os("HOME")
.or_else(|| std::env::var_os("USERPROFILE"));
home.map(|_| ()).ok_or_else(|| std::io::Error::new(
std::io::ErrorKind::NotFound,
"set CLAW_CONFIG_HOME, HOME, or USERPROFILE before OAuth operations",
))
}
// before any oauth call:
ensure_config_home()?; Try / catch
match runtime::oauth::load_credentials() {
Ok(creds) => { /* ... */ }
Err(e) if e.kind() == std::io::ErrorKind::NotFound
&& e.to_string().contains("HOME is not set") => {
eprintln!("no home directory: set CLAW_CONFIG_HOME or HOME");
}
Err(e) => return Err(e),
} Prevention
- Always set CLAW_CONFIG_HOME in containers, systemd units, cron jobs, and tests — it is the deterministic override with no OS-dependent semantics
- When spawning claw from other processes, inherit or explicitly set HOME/USERPROFILE rather than passing a scrubbed env
- In CI, export CLAW_CONFIG_HOME=$(mktemp -d) to isolate tests from the runner's home state
When it happens
Trigger: Any call that resolves the credentials path, e.g. the load/save helpers at oauth.rs:266-296 that call credentials_home_dir()?.join("credentials.json") — typically triggered by starting an OAuth login flow or refreshing stored tokens. Occurs when the process is spawned with a scrubbed environment (env -i, minimal Docker containers, systemd units without EnvironmentFile, cron or CI runners that drop HOME).
Common situations: Running the claw binary in Docker/scratch containers that never set HOME; Windows services or scheduled tasks where USERPROFILE is not inherited; su/sudo invocations that reset environment variables; CI pipelines using env -u HOME; test harnesses that clear the environment between cases.
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
- credentials file must contain a JSON object
- unable to resolve a skills install root; set CLAW_CONFIG_HOM
- session file was removed during save (possible concurrent mo
- session file was removed during write (possible concurrent m
- missing_flag_value: missing value for --cwd. Usage: --cwd <p
AI-assisted analysis of ultraworkers/claw-code@08106b0c37 (2026-08-18).
Data as JSON: /api/errors/fc344095cf4d5cc2.
Report an issue: GitHub.