affaan-m/ECC · error · Error
Failed to run gh: ${result.error.message}
Error message
Failed to run gh: ${result.error.message} What it means
Thrown by scripts/runGhJson in scripts/work-items.js when Node's spawnSync returns an error object (result.error set) instead of a process result. This happens when the `gh` executable cannot be spawned at all — most commonly because the GitHub CLI is not installed, not on PATH, or (when ECC_GH_SHIM is set) the shim path is invalid. It is an environment-level failure, not a GitHub API failure.
Source
Thrown at scripts/work-items.js:156
const parsed = Number.parseInt(value, 10);
if (!Number.isFinite(parsed) || parsed <= 0) {
throw new Error(`Invalid limit: ${value}`);
}
return parsed;
}
function runGhJson(args) {
const shimPath = process.env.ECC_GH_SHIM;
const command = shimPath ? process.execPath : 'gh';
const commandArgs = shimPath ? [shimPath, ...args] : args;
const displayCommand = shimPath ? `node ${shimPath} ${args.join(' ')}` : `gh ${args.join(' ')}`;
const result = spawnSync(command, commandArgs, {
encoding: 'utf8',
maxBuffer: 10 * 1024 * 1024
});
if (result.error) {
throw new Error(`Failed to run gh: ${result.error.message}`);
}
if (result.status !== 0) {
throw new Error(`${displayCommand} failed: ${(result.stderr || result.stdout || '').trim()}`);
}
try {
return JSON.parse(result.stdout || '[]');
} catch (error) {
throw new Error(`${displayCommand} returned invalid JSON: ${error.message}`);
}
}
function slugifyWorkItemSegment(value) {
return (
String(value || '')
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')View on GitHub (pinned to 01e15490f0)
Solutions
- Install the GitHub CLI (e.g. `brew install gh`, `apt install gh`, or see https://cli.github.com) and confirm `which gh` resolves.
- Authenticate with `gh auth login` (a missing auth causes a different error — error 478 — but confirming gh is present is step one).
- If using ECC_GH_SHIM, verify the shim file path exists and is executable.
- In CI, add an explicit gh installation step and a `gh --version` smoke check before invoking sync-github.
Example fix
// before node scripts/work-items.js sync-github --repo owner/repo # Error: Failed to run gh: spawn gh ENOENT // after brew install gh gh auth login node scripts/work-items.js sync-github --repo owner/repo
Defensive patterns
Strategy: validation
Validate before calling
const { spawnSync } = require('child_process');
function ghAvailable() {
const r = spawnSync('gh', ['--version'], { encoding: 'utf8' });
return r.status === 0 && /gh version/.test(r.stdout || '');
}
if (!ghAvailable()) {
throw new Error('GitHub CLI (gh) is required for sync-github. Install from https://cli.github.com');
} Try / catch
// retry once after a short delay if gh spawn fails transiently
async function runSyncGithubWithRetry(args, retries = 1) {
for (let attempt = 0; attempt <= retries; attempt++) {
try {
return runWorkItems(args);
} catch (e) {
if (attempt === retries || !/Failed to run gh/.test(e.message)) throw e;
await new Promise(r => setTimeout(r, 2000));
}
}
} Prevention
- Add a `gh --version` smoke check in CI before any sync-github step.
- Install gh in your Docker/CI image explicitly rather than relying on the runner.
- If using ECC_GH_SHIM, assert the shim file exists and is executable before invoking.
When it happens
Trigger: Running `node scripts/work-items.js sync-github --repo owner/repo` on a machine without `gh` installed; CI image that lacks the gh CLI; ECC_GH_SHIM pointing to a nonexistent file; gh present but not executable (permissions).
Common situations: Fresh dev machine or minimal Docker image without gh; a CI runner that installs gh conditionally and skipped it; setting ECC_GH_SHIM to a test shim that was since deleted.
Related errors
- ${displayCommand} failed: ${(result.stderr || result.stdout
- ${displayCommand} returned invalid JSON: ${error.message}
- ${command} ${args.join(' ')} failed: ${result.error.message}
- ECC_PROJECT_DIR must be an absolute path within /workspace.
- ${flagName} requires a value
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/bdb6e70ad9454b15.
Report an issue: GitHub.