{"record":{"id":"9aca46ccde70d57e","repo":"aaif-goose/goose","slug":"failed-to-run-gh-auth-login","errorCode":null,"errorMessage":"Failed to run `gh auth login`","messagePattern":"Failed to run `gh auth login`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/goose-cli/src/recipes/github_recipe.rs","lineNumber":123,"sourceCode":"pub fn ensure_gh_authenticated() -> Result<()> {\n    // Check authentication status\n    let status = Command::new(\"gh\")\n        .args([\"auth\", \"status\"])\n        .set_no_window()\n        .status()\n        .map_err(|_| {\n            anyhow::anyhow!(\"Failed to run `gh auth status`. Make sure you have `gh` installed.\")\n        })?;\n\n    if status.success() {\n        return Ok(());\n    }\n    println!(\"GitHub CLI is not authenticated. Launching `gh auth login`...\");\n    // Run `gh auth login` interactively\n    let login_status = Command::new(\"gh\")\n        .args([\"auth\", \"login\", \"--git-protocol\", \"https\"])\n        .status()\n        .map_err(|_| anyhow::anyhow!(\"Failed to run `gh auth login`\"))?;\n\n    if !login_status.success() {\n        Err(anyhow::anyhow!(\"Failed to authenticate using GitHub CLI.\"))\n    } else {\n        Ok(())\n    }\n}\n\nfn temp_child_name(name: &str) -> String {\n    let mut child = String::with_capacity(name.len());\n    for ch in name.chars() {\n        match ch {\n            '/' | '\\\\' => child.push_str(\"__\"),\n            ch if ch.is_ascii_alphanumeric() || ch == '-' || ch == '_' || ch == '.' => {\n                child.push(ch)\n            }\n            _ => child.push('_'),\n        }","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/aaif-goose/goose/blob/3810898a7447ec3299be72e223d3570a7aabf0ab/crates/goose-cli/src/recipes/github_recipe.rs#L105-L141","documentation":"When `gh auth status` reports the CLI is not authenticated, goose launches interactive `gh auth login --git-protocol https` (crates/goose-cli/src/recipes/github_recipe.rs:118-123). This error fires only when that command could not be spawned at all — the io::Error from Command::status() is dropped and this static message is substituted.","triggerScenarios":"`gh` passed the earlier `auth status` spawn but the `auth login` spawn now fails: gh binary removed/moved between calls, exec permission or format error, or fork/exec resource failure (EAGAIN) on an exhausted system. Note it is a spawn failure, not a failed login attempt.","commonSituations":"Extremely rare standalone; usually accompanies [126] when gh disappears mid-session (brew upgrade replacing the binary, PATH change in a wrapper script) or under heavy resource pressure where the second spawn hits a process/thread limit.","solutions":["Confirm gh is still resolvable: `command -v gh && gh auth status` in the same shell","Run `gh auth login --git-protocol https` manually once, then retry the goose command so the interactive path is never needed","If spawns fail from resource exhaustion, free processes/threads and retry"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Rust: distinguish spawn failure from failed login by inspecting the io error\nlet out = Command::new(\"gh\").args([\"auth\", \"login\", \"--git-protocol\", \"https\"]).status();\nmatch out {\n    Err(io_err) if io_err.kind() == std::io::ErrorKind::NotFound => {\n        eprintln!(\"gh is not installed: {io_err}\");\n    }\n    Err(io_err) => eprintln!(\"spawn failed: {io_err}\"),\n    Ok(st) if !st.success() => eprintln!(\"login flow did not complete\"),\n    Ok(_) => {}\n}","preventionTips":["Authenticate once interactively up front so goose never needs to launch the login flow","Keep gh on a stable PATH throughout long goose sessions"],"tags":["goose-cli","github-cli","authentication","external-tool"],"backgroundTag":null,"analyzedSha":"3810898a7447ec3299be72e223d3570a7aabf0ab","analyzedAt":"2026-08-16T10:14:26.282Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}