aaif-goose/goose · error

Failed to run `gh auth login`

Error message

Failed to run `gh auth login`

What it means

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.

Source

Thrown at crates/goose-cli/src/recipes/github_recipe.rs:123

pub fn ensure_gh_authenticated() -> Result<()> {
    // Check authentication status
    let status = Command::new("gh")
        .args(["auth", "status"])
        .set_no_window()
        .status()
        .map_err(|_| {
            anyhow::anyhow!("Failed to run `gh auth status`. Make sure you have `gh` installed.")
        })?;

    if status.success() {
        return Ok(());
    }
    println!("GitHub CLI is not authenticated. Launching `gh auth login`...");
    // Run `gh auth login` interactively
    let login_status = Command::new("gh")
        .args(["auth", "login", "--git-protocol", "https"])
        .status()
        .map_err(|_| anyhow::anyhow!("Failed to run `gh auth login`"))?;

    if !login_status.success() {
        Err(anyhow::anyhow!("Failed to authenticate using GitHub CLI."))
    } else {
        Ok(())
    }
}

fn temp_child_name(name: &str) -> String {
    let mut child = String::with_capacity(name.len());
    for ch in name.chars() {
        match ch {
            '/' | '\\' => child.push_str("__"),
            ch if ch.is_ascii_alphanumeric() || ch == '-' || ch == '_' || ch == '.' => {
                child.push(ch)
            }
            _ => child.push('_'),
        }

View on GitHub (pinned to 3810898a74)

Solutions

  1. Confirm gh is still resolvable: `command -v gh && gh auth status` in the same shell
  2. Run `gh auth login --git-protocol https` manually once, then retry the goose command so the interactive path is never needed
  3. If spawns fail from resource exhaustion, free processes/threads and retry
Defensive patterns

Strategy: try-catch

Try / catch

// Rust: distinguish spawn failure from failed login by inspecting the io error
let out = Command::new("gh").args(["auth", "login", "--git-protocol", "https"]).status();
match out {
    Err(io_err) if io_err.kind() == std::io::ErrorKind::NotFound => {
        eprintln!("gh is not installed: {io_err}");
    }
    Err(io_err) => eprintln!("spawn failed: {io_err}"),
    Ok(st) if !st.success() => eprintln!("login flow did not complete"),
    Ok(_) => {}
}

Prevention

When it happens

Trigger: `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.

Common situations: 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.

Related errors


AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16). Data as JSON: /api/errors/9aca46ccde70d57e. Report an issue: GitHub.