jlcodes99/cockpit-tools · critical

无法获取用户主目录

Error message

无法获取用户主目录

What it means

get_codex_home resolves the Codex data directory: first from the CODEX_HOME environment variable, otherwise from dirs::home_dir(). If neither is available it panics with '无法获取用户主目录' (cannot get user home directory). It is called throughout account/API-key/auth.json operations.

Source

Thrown at crates/cockpit-core/src/modules/codex_account_core_provider.rs:582

    if !status.is_success() {
        return Err(format!(
            "账号信息接口返回错误 {},body_len={}",
            status,
            body.len()
        ));
    }

    let payload: serde_json::Value =
        serde_json::from_str(&body).map_err(|e| format!("账号信息 JSON 解析失败: {}", e))?;
    Ok(parse_account_profile_from_check_response(&payload, account))
}

/// 获取 Codex 数据目录
pub fn get_codex_home() -> PathBuf {
    if let Some(from_env) = resolve_codex_home_from_env() {
        return from_env;
    }
    dirs::home_dir().expect("无法获取用户主目录").join(".codex")
}

fn resolve_codex_home_from_env() -> Option<PathBuf> {
    let raw = std::env::var("CODEX_HOME").ok()?;
    let trimmed = raw.trim();
    if trimmed.is_empty() {
        return None;
    }

    // 兼容用户使用 setx / shell 时可能包裹的引号
    let unquoted = trimmed.trim_matches('"').trim_matches('\'').trim();
    if unquoted.is_empty() {
        return None;
    }

    Some(PathBuf::from(unquoted))
}

View on GitHub (pinned to 1ed8b77992)

Solutions

  1. Set the CODEX_HOME environment variable to an absolute writable path before invoking.
  2. Ensure HOME (Unix) or USERPROFILE (Windows) is set correctly for the process.
  3. If running as a service, configure the service account with a profile directory or inject the env var at launch.
  4. Wrap the call site to catch the panic (catch_unwind) or prefer an API variant returning Option/Result if one is added.

Example fix

// before
let home = get_codex_home(); // panics if no home dir

// after
let home = match std::env::var("CODEX_HOME") {
    Ok(v) if !v.trim().is_empty() => std::path::PathBuf::from(v.trim()),
    _ => {
        if std::env::var_os("HOME").is_none()
            && std::env::var_os("USERPROFILE").is_none()
        {
            eprintln!("no home directory; aborting");
            return;
        }
        get_codex_home()
    }
};
Defensive patterns

Strategy: validation

Validate before calling

fn home_resolvable() -> bool {
    std::env::var("CODEX_HOME").map_or(false, |v| !v.trim().is_empty())
        || std::env::var_os("HOME").is_some()
        || std::env::var_os("USERPROFILE").is_some()
}

Try / catch

std::panic::catch_unwind(get_codex_home).map_err(|_| anyhow::anyhow!("无法获取用户主目录"))

Prevention

When it happens

Trigger: Calling get_codex_home (directly or via get_current_account, update_api_key_credentials, get_auth_json_path, load_current_quick_config, save_current_quick_config) when CODEX_HOME is unset/blank AND the OS cannot determine the home directory (dirs::home_dir() returns None).

Common situations: Running as a Windows service or under an account without a profile; stripped environment in CI containers (no HOME); malformed passwd entry on Unix; SYSTEM-account execution.

Related errors


AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05). Data as JSON: /api/errors/cf499a54eb5b684d. Report an issue: GitHub.