{"record":{"id":"cf499a54eb5b684d","repo":"jlcodes99/cockpit-tools","slug":"error-cf499a","errorCode":null,"errorMessage":"无法获取用户主目录","messagePattern":"无法获取用户主目录","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/cockpit-core/src/modules/codex_account_core_provider.rs","lineNumber":582,"sourceCode":"    if !status.is_success() {\n        return Err(format!(\n            \"账号信息接口返回错误 {}，body_len={}\",\n            status,\n            body.len()\n        ));\n    }\n\n    let payload: serde_json::Value =\n        serde_json::from_str(&body).map_err(|e| format!(\"账号信息 JSON 解析失败: {}\", e))?;\n    Ok(parse_account_profile_from_check_response(&payload, account))\n}\n\n/// 获取 Codex 数据目录\npub fn get_codex_home() -> PathBuf {\n    if let Some(from_env) = resolve_codex_home_from_env() {\n        return from_env;\n    }\n    dirs::home_dir().expect(\"无法获取用户主目录\").join(\".codex\")\n}\n\nfn resolve_codex_home_from_env() -> Option<PathBuf> {\n    let raw = std::env::var(\"CODEX_HOME\").ok()?;\n    let trimmed = raw.trim();\n    if trimmed.is_empty() {\n        return None;\n    }\n\n    // 兼容用户使用 setx / shell 时可能包裹的引号\n    let unquoted = trimmed.trim_matches('\"').trim_matches('\\'').trim();\n    if unquoted.is_empty() {\n        return None;\n    }\n\n    Some(PathBuf::from(unquoted))\n}\n","sourceCodeStart":564,"sourceCodeEnd":600,"githubUrl":"https://github.com/jlcodes99/cockpit-tools/blob/1ed8b77992d62ca81fabf744deb0839ad361d5bf/crates/cockpit-core/src/modules/codex_account_core_provider.rs#L564-L600","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Set the CODEX_HOME environment variable to an absolute writable path before invoking.","Ensure HOME (Unix) or USERPROFILE (Windows) is set correctly for the process.","If running as a service, configure the service account with a profile directory or inject the env var at launch.","Wrap the call site to catch the panic (catch_unwind) or prefer an API variant returning Option/Result if one is added."],"exampleFix":"// before\nlet home = get_codex_home(); // panics if no home dir\n\n// after\nlet home = match std::env::var(\"CODEX_HOME\") {\n    Ok(v) if !v.trim().is_empty() => std::path::PathBuf::from(v.trim()),\n    _ => {\n        if std::env::var_os(\"HOME\").is_none()\n            && std::env::var_os(\"USERPROFILE\").is_none()\n        {\n            eprintln!(\"no home directory; aborting\");\n            return;\n        }\n        get_codex_home()\n    }\n};","handlingStrategy":"validation","validationCode":"fn home_resolvable() -> bool {\n    std::env::var(\"CODEX_HOME\").map_or(false, |v| !v.trim().is_empty())\n        || std::env::var_os(\"HOME\").is_some()\n        || std::env::var_os(\"USERPROFILE\").is_some()\n}","typeGuard":null,"tryCatchPattern":"std::panic::catch_unwind(get_codex_home).map_err(|_| anyhow::anyhow!(\"无法获取用户主目录\"))","preventionTips":["Set CODEX_HOME explicitly in service/CI/container environments","Verify HOME/USERPROFILE is present before account operations","Run the app under a real user account with a profile, not a bare service identity","Fail fast at startup with a clear message if the home directory cannot be resolved"],"tags":["panic","home-directory","environment","codex"],"backgroundTag":"missing-home-directory","analyzedSha":"1ed8b77992d62ca81fabf744deb0839ad361d5bf","analyzedAt":"2026-09-05T09:51:41.178Z","contentChangedAt":"2026-09-05T09:51:41.178Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}