affaan-m/ECC · error
gh returned invalid JSON
Error message
gh ${args.join(' ')} returned invalid JSON: ${error.message} What it means
runGhJson parses the stdout of a gh command as JSON and throws this when JSON.parse fails, wrapping the underlying parse error message. It indicates gh produced output the module did not expect — non-JSON text such as warnings, human-readable error banners, or HTML from a proxy.
Solutions
- Run the exact command printed in the message manually and inspect the raw output.
- Upgrade or pin the gh CLI version to one matching the module's expectations.
- Remove proxy interference or ensure HTTPS_PROXY points to a trusted proxy returning real responses.
- Re-authenticate (`gh auth login` / fresh GH_TOKEN) so gh stops emitting interactive banners.
Example fix
// before
const payload = runGhJson(['api', 'repos/o/r']);
// after
try {
const payload = runGhJson(['api', 'repos/o/r']);
} catch (e) {
if (/invalid JSON/.test(e.message)) {
console.error('gh output not JSON — check gh version/auth:', e.message);
}
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
const probe = spawnSync('gh', ['--version'], { encoding: 'utf8' });
if (probe.status !== 0) throw new Error('gh CLI unavailable or wrong version'); Try / catch
try {
const data = runGhJson(args);
return data;
} catch (e) {
if (/returned invalid JSON/.test(e.message)) {
console.error('Unexpected gh output — check gh version, proxy, and auth:', e.message);
}
throw e;
} Prevention
- Pin the gh CLI version in CI to match what the module expects.
- Ensure proxies don't inject HTML into HTTPS responses.
- Re-authenticate before long-running jobs so gh doesn't emit interactive banners.
When it happens
Trigger: gh emitting non-JSON output for a command whose stdout should be JSON: gh printing a login prompt/banner, proxy/captive-portal HTML pages, gh versions with different output shapes, or stderr warnings interleaved when output is redirected.
Common situations: Pinned gh version differs from expected (flag unsupported, output format changed); corporate proxy injecting HTML; gh session expired and gh prompts interactively; calling a gh subcommand that doesn't support --json.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/6d18975b20edcfcf.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/github-discussions.js:51
return result.stdout || '';
}
function runGhJson(args, options = {}) {
const shimPath = process.env.ECC_GH_SHIM;
const command = shimPath ? process.execPath : 'gh';
const commandArgs = shimPath ? [shimPath, ...args] : args;
const env = { ...process.env };
if (!options.useEnvGithubToken) {
delete env.GITHUB_TOKEN;
}
const stdout = runCommand(command, commandArgs, { env });
try {
return JSON.parse(stdout || 'null');
} catch (error) {
throw new Error(`gh ${args.join(' ')} returned invalid JSON: ${error.message}`);
}
}
function discussionNeedsMaintainerTouch(discussion) {
if (MAINTAINER_ASSOCIATIONS.has(discussion.authorAssociation)) {
return false;
}
if (
discussion.answer
&& MAINTAINER_ASSOCIATIONS.has(discussion.answer.authorAssociation)
) {
return false;
}
const comments = discussion.comments && Array.isArray(discussion.comments.nodes)
? discussion.comments.nodes
: [];View on GitHub (pinned to 8321021c54)