{"record":{"id":"46bbdf86ef47dad4","repo":"nikivdev/code","slug":"gh-api-user-failed","errorCode":null,"errorMessage":"gh api user failed","messagePattern":"gh api user failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/repos.rs","lineNumber":1473,"sourceCode":"        owner: owner.to_string(),\n        repo: repo.to_string(),\n    })\n}\n\nfn normalize_git_url(url: &str) -> String {\n    url.trim()\n        .trim_end_matches('/')\n        .trim_end_matches(\".git\")\n        .to_string()\n}\n\nfn github_login() -> Result<String> {\n    let output = Command::new(\"gh\")\n        .args([\"api\", \"user\", \"-q\", \".login\"])\n        .output()\n        .context(\"failed to run gh api user\")?;\n    if !output.status.success() {\n        bail!(\"gh api user failed\");\n    }\n    let login = String::from_utf8_lossy(&output.stdout).trim().to_string();\n    if login.is_empty() {\n        bail!(\"gh login was empty\");\n    }\n    Ok(login)\n}\n\nfn resolve_remote_default_branch_in(repo_root: &Path, remote: &str) -> Option<String> {\n    let head_ref = format!(\"refs/remotes/{remote}/HEAD\");\n    if let Ok(symbolic) = git_capture_in(repo_root, &[\"symbolic-ref\", &head_ref]) {\n        let prefix = format!(\"refs/remotes/{remote}/\");\n        if let Some(branch) = symbolic.trim().strip_prefix(&prefix)\n            && !branch.is_empty()\n        {\n            return Some(branch.to_string());\n        }\n    }","sourceCodeStart":1455,"sourceCodeEnd":1491,"githubUrl":"https://github.com/nikivdev/code/blob/a747e741ae92c09071d0ae946ab48488adcff1ce/src/repos.rs#L1455-L1491","documentation":"github_login shells out to `gh api user -q .login` to identify the authenticated GitHub user; if the gh command completes but exits non-zero, this bail fires. It means the GitHub CLI is installed but the API call failed (auth, network, or token issues).","triggerScenarios":"`gh api user` returns a non-zero exit status while resolving the login during clone bootstrap / private-mirror flows.","commonSituations":"`gh` not logged in (`gh auth login` never run); expired or revoked token; GH_TOKEN/GITHUB_TOKEN env var overriding invalid credentials; network/VPN blocking api.github.com.","solutions":["Run `gh auth login` to authenticate the GitHub CLI.","Verify auth with `gh auth status` and refresh an expired token (`gh auth refresh`).","Check GH_TOKEN/GITHUB_TOKEN env vars are unset or valid.","Test connectivity: `gh api user` directly to see gh's own error."],"exampleFix":"// before\n$ f clone private/repo   // gh api user -> exit 1\n// after\n$ gh auth login\n$ gh auth status   # verify logged in\n$ f clone private/repo","handlingStrategy":"validation","validationCode":"fn gh_ready() -> bool {\n    std::process::Command::new(\"gh\")\n        .args([\"auth\", \"status\"])\n        .output()\n        .map(|o| o.status.success())\n        .unwrap_or(false)\n}\n// only call flows that use github_login when gh_ready()","typeGuard":null,"tryCatchPattern":"match github_login() {\n    Err(e) if e.to_string().contains(\"gh api user failed\") => {\n        // re-auth then retry\n        run_gh_auth_login()?;\n        let login = github_login()?;\n    }\n    r => r?,\n}","preventionTips":["Run `gh auth login` during machine setup and keep tokens fresh.","Check `gh auth status` before automations that depend on gh.","Avoid exporting invalid GH_TOKEN/GITHUB_TOKEN values.","Monitor gh/CLI upgrades that change auth behavior in CI images."],"tags":["github","cli","authentication","gh"],"backgroundTag":"gh-cli-auth-failed","analyzedSha":"a747e741ae92c09071d0ae946ab48488adcff1ce","analyzedAt":"2026-09-01T22:43:55.719Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}