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

  1. Run the exact command printed in the message manually and inspect the raw output.
  2. Upgrade or pin the gh CLI version to one matching the module's expectations.
  3. Remove proxy interference or ensure HTTPS_PROXY points to a trusted proxy returning real responses.
  4. 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

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.

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)