{"record":{"id":"616a9a7afe455320","repo":"xai-org/grok-build","slug":"failed-to-open-e","errorCode":null,"errorMessage":"failed to open {}: {e}","messagePattern":"failed to open (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-workspace/src/hub_auth/mod.rs","lineNumber":364,"sourceCode":"/// the truncate-in-place corruption window when the long-lived binary rewrites\n/// auth.json.\nfn write_json_atomic(path: &Path, value: &serde_json::Value) -> anyhow::Result<()> {\n    use std::io::Write;\n\n    let json = serde_json::to_string_pretty(value)?;\n    let tmp = path.with_extension(format!(\"json.{}.tmp\", std::process::id()));\n\n    let mut opts = std::fs::OpenOptions::new();\n    opts.write(true).create(true).truncate(true);\n    #[cfg(unix)]\n    {\n        use std::os::unix::fs::OpenOptionsExt;\n        opts.mode(0o600);\n    }\n\n    let mut file = opts\n        .open(&tmp)\n        .map_err(|e| anyhow::anyhow!(\"failed to open {}: {e}\", tmp.display()))?;\n    file.write_all(json.as_bytes())?;\n    file.sync_all()?;\n    drop(file);\n\n    #[cfg(windows)]\n    let _ = std::fs::remove_file(path);\n\n    if let Err(e) = std::fs::rename(&tmp, path) {\n        let _ = std::fs::remove_file(&tmp);\n        return Err(anyhow::anyhow!(\"failed to replace {}: {e}\", path.display()));\n    }\n    Ok(())\n}\n\n/// Build a hub auth provider for `hub_url`. `auth_config` overrides\n/// the default credential path (`~/.grok/auth.json`).\n///\n/// `refresh_cfg.enabled` selects the workspace-owned proactive refresher;","sourceCodeStart":346,"sourceCodeEnd":382,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-workspace/src/hub_auth/mod.rs#L346-L382","documentation":"`write_json_atomic` persists refreshed tokens by writing JSON to a temp file next to the target and renaming it into place. This error is thrown when the temp file cannot be opened for writing. On Unix the file is created with mode 0600 so credentials are protected. It wraps the underlying `std::io::Error` (permission denied, read-only filesystem, missing parent dir, etc.).","triggerScenarios":"`write_refreshed_token` -> `write_json_atomic` when `OpenOptions::create(true).write(true).truncate(true).open(&tmp)` fails: the directory does not exist, the process lacks write permission, the filesystem is full/read-only, or an AV/another process holds a conflicting lock on Windows.","commonSituations":"auth.json directory owned by root or another user; $HOME on a read-only mount or full disk; container running as non-root with a volume mounted read-only; corrupted GROK_HOME path.","solutions":["Check permissions on the directory containing auth.json (should be writable by the current user): `ls -ld ~/.grok`.","Verify the disk is not full (`df -h`) and the filesystem is mounted read-write (`mount | grep ...`).","Ensure $GROK_HOME/$HOME point to an existing, writable directory; create `~/.grok` if missing.","On Windows, check that no antivirus/backup process is locking the temp file."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// The error wraps the io::Error; downcast to inspect the OS error kind\nmatch write_refreshed_token(&auth_path, &scope_key, &event) {\n    Ok(()) => {},\n    Err(e) => {\n        if let Some(io_err) = e.chain().find_map(|c| c.downcast_ref::<std::io::Error>()) {\n            match io_err.kind() {\n                std::io::ErrorKind::PermissionDenied => eprintln!(\"fix perms on {}\", auth_path.display()),\n                std::io::ErrorKind::StorageFull => eprintln!(\"disk full\"),\n                _ => eprintln!(\"persist failed: {io_err}\"),\n            }\n        }\n    }\n}","preventionTips":["Ensure ~/.grok exists and is owned/writable by the running user before starting sessions.","Keep a few MB of free disk space; token refresh writes fail on full disks.","Avoid running the CLI as a different user (sudo) than the one that owns auth.json.","On Windows, exclude the credentials directory from aggressive AV/backup locking."],"tags":["filesystem","permissions","io","rust"],"backgroundTag":"permission-denied","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}