{"record":{"id":"00d7f49f76099bcb","repo":"nikivdev/code","slug":"gh-is-installed-but-not-working-00d7f4","errorCode":null,"errorMessage":"`gh` is installed but not working","messagePattern":"`gh` is installed but not working","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/release_signing.rs","lineNumber":225,"sourceCode":"    ensure_gh_available()?;\n    for key in SIGNING_KEYS {\n        let value = vars.get(key).expect(\"checked above\");\n        gh_secret_set(opts.repo.as_deref(), key, value)?;\n        println!(\"✓ Set GitHub secret: {}\", key);\n    }\n\n    Ok(())\n}\n\nfn ensure_gh_available() -> Result<()> {\n    let status = Command::new(\"gh\")\n        .args([\"--version\"])\n        .stdout(Stdio::null())\n        .stderr(Stdio::null())\n        .status()\n        .context(\"failed to run `gh` (GitHub CLI)\")?;\n    if !status.success() {\n        bail!(\"`gh` is installed but not working\");\n    }\n    Ok(())\n}\n\nfn gh_secret_set(repo: Option<&str>, name: &str, value: &str) -> Result<()> {\n    let mut cmd = Command::new(\"gh\");\n    cmd.args([\"secret\", \"set\", name]);\n    if let Some(repo) = repo {\n        cmd.args([\"--repo\", repo]);\n    }\n    // Avoid passing secrets via argv (ps); `gh secret set` reads from stdin when --body is omitted.\n\n    let mut child = cmd\n        .stdin(Stdio::piped())\n        .stdout(Stdio::null())\n        .spawn()\n        .with_context(|| format!(\"failed to spawn `gh secret set {}`\", name))?;\n","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/nikivdev/code/blob/a747e741ae92c09071d0ae946ab48488adcff1ce/src/release_signing.rs#L207-L243","documentation":"ensure_gh_available runs `gh --version` (with output discarded) before syncing secrets. If gh is found but exits non-zero, the tool concludes the GitHub CLI is broken and bails. It is distinct from the 'gh not installed' case, which fails earlier with a different error.","triggerScenarios":"`gh --version` returns a non-zero exit status during `f release signing sync`.","commonSituations":"Broken or partially upgraded gh binary; incompatible gh installed via mismatched package manager; permissions/exec issues; corrupted PATH entry pointing to a stub.","solutions":["Reinstall/upgrade gh (`brew upgrade gh` or your package manager's equivalent)","Run `gh --version` and `gh auth status` manually to see the failure","Check PATH for shadowing/broken `gh` binaries (`which -a gh`)"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const { status } = spawnSync(\"gh\", [\"--version\"], { stdio: \"ignore\" });\nif (status !== 0) throw new Error(\"gh is broken; reinstall before syncing signing secrets\");","typeGuard":null,"tryCatchPattern":"try {\n  run([\"f\", \"release\", \"signing\", \"sync\"]);\n} catch (e) {\n  if (String(e).includes(\"not working\") || String(e).includes(\"failed to run `gh`\")) {\n    console.error(\"Reinstall the GitHub CLI (brew upgrade gh) and run `gh auth login`.\");\n  } else throw e;\n}","preventionTips":["Install gh via a maintained package manager and keep it updated","Run `gh --version` and `gh auth status` as pipeline preflight checks","Avoid shadowing `gh` with broken binaries on PATH"],"tags":["github-cli","process-exit","tooling"],"backgroundTag":"cli-tool-broken","analyzedSha":"a747e741ae92c09071d0ae946ab48488adcff1ce","analyzedAt":"2026-09-01T22:43:55.719Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}