pbakaus/impeccable · error · Error
gh ${args.join(' ')} failed with exit ${result.status}: ${re
Error message
gh ${args.join(' ')} failed with exit ${result.status}: ${result.stderr || result.stdout} What it means
Thrown by runGh in the GitHub sheriff script when a spawned `gh` command exits with a non-zero status (and allowFailure is not set). The message embeds the full gh argument list, the exit code, and stderr (falling back to stdout) so the underlying gh failure is visible. This is the primary surface for any gh-level failure: auth errors, rate limits, missing repos, and permission denials all bubble up here.
Source
Thrown at scripts/github/sheriff.mjs:787
function runGhJson(args) {
const result = runGh(args, { quiet: true });
try {
return JSON.parse(result.stdout || '{}');
} catch (err) {
throw new Error(`Failed to parse gh JSON output: ${err.message}`);
}
}
function runGh(args, options = {}) {
const result = spawnSync('gh', args, {
encoding: 'utf-8',
env: process.env,
});
if (!options.quiet && result.stdout) process.stdout.write(result.stdout);
if (!options.quiet && result.stderr) process.stderr.write(result.stderr);
if (result.error) throw result.error;
if (result.status !== 0 && !options.allowFailure) {
throw new Error(`gh ${args.join(' ')} failed with exit ${result.status}: ${result.stderr || result.stdout}`);
}
return result;
}
function printHelp() {
console.log(`Usage: node scripts/github/sheriff.mjs [--repo owner/name] [--apply]
Default mode is a dry run. The scheduled workflow runs with:
--apply --warning-days 7 --close-days 14
Options:
--apply mutate labels, comments, and stale PR state
--dry-run print changes without mutating GitHub
--repo owner/name repository to inspect (defaults to GITHUB_REPOSITORY)
--warning-days n warn waiting PRs after n days open (default: 7)
--close-days n close waiting PRs after n days open (default: 14)
--maintainers a,b maintainer logins allowed to use /sheriff wait
--regular-contributors a,b contributors exempt from auto-close unless --auto-close-regulars is setView on GitHub (pinned to d14711ae3d)
Solutions
- Run `gh auth status` and re-authenticate with `gh auth login` or by setting a valid GITHUB_TOKEN.
- Copy the exact gh args from the error message and run them manually to reproduce the real gh error.
- Verify --repo owner/name is correct and that the token has the needed scopes (repo / read:org).
- If rate-limited, wait and retry; for secondary limits, reduce concurrency or batch size in the sheriff config.
- Pass { allowFailure: true } to runGh for non-critical calls where a gh failure should not abort the whole run.
Example fix
// before
const result = runGh(['pr', 'list', '--repo', repo]);
// after: preflight auth so the failure is diagnosed before the sweep
const authed = runGh(['auth', 'status'], { allowFailure: true, quiet: true });
if (authed.status !== 0) {
throw new Error('gh is not authenticated; run `gh auth login` before sheriff');
}
const result = runGh(['pr', 'list', '--repo', repo]); Defensive patterns
Strategy: try-catch
Validate before calling
// Preflight: gh installed + authenticated before the sweep starts.
import { spawnSync } from 'node:child_process';
function ghReady() {
const r = spawnSync('gh', ['auth', 'status'], { encoding: 'utf-8' });
return r.status === 0;
} Try / catch
// Wrap runGh so non-zero exits include a hint and allow opt-in continuation.
function runGhSafe(args, { allowFailure = false } = {}) {
try {
return runGh(args, { quiet: true, allowFailure });
} catch (err) {
const msg = String(err.message || err);
if (/rate limit/i.test(msg)) throw new Error('GitHub rate limit hit; back off and retry.');
if (/authentication|credentials|token/i.test(msg)) throw new Error('gh auth invalid; run `gh auth login`.');
throw err;
}
} Prevention
- Run `gh auth status` before any sweep and fail fast with a clear message.
- Pass allowFailure:true for non-critical gh calls so one failure does not abort everything.
- Log the exact gh args on failure so the command is reproducible by hand.
- Keep the GITHUB_TOKEN fresh in scheduled workflows; tokens expire.
When it happens
Trigger: Expired or missing GITHUB_TOKEN / gh auth; querying a repo the token cannot read; hitting GitHub primary or secondary rate limits; gh not installed (though that surfaces as result.error first); a branch-protection or permission rejection on a mutate subcommand; --repo pointing at a typo'd owner/name.
Common situations: A scheduled stale-PR workflow whose token expired; running sheriff locally without `gh auth login`; a fork where the actor lacks write access; GitHub secondary rate limits kicking in during a bulk label/close sweep; CI image missing the gh binary.
Related errors
- Failed to parse gh JSON output: ${err.message}
- Missing repository. Pass --repo owner/name or set GITHUB_REP
- puppeteer is required for URL scanning. Install: npm install
- Unknown ignore-rule flag: ${arg}
- Pass a rule id, e.g. ${IMPECCABLE_COMMAND} hooks ignore-rule
AI-assisted analysis of pbakaus/impeccable@d14711ae3d (2026-08-13).
Data as JSON: /api/errors/35051e2871966703.
Report an issue: GitHub.