{"record":{"id":"1a948fa93a8285f0","repo":"affaan-m/ECC","slug":"gh-args-join-returned-invalid-json-erro","errorCode":null,"errorMessage":"gh ${args.join(' ')} returned invalid JSON: ${error.message}","messagePattern":"gh (.+?) returned invalid JSON: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/github-coordination/gh-api.js","lineNumber":78,"sourceCode":"// privileges.\nfunction runGh(args, options = {}) {\n  const shimPath = process.env.ECC_GH_SHIM;\n  const command = shimPath ? process.execPath : 'gh';\n  const commandArgs = shimPath ? [shimPath, ...args] : args;\n  const env = { ...process.env };\n\n  if (options.stripGithubToken) {\n    delete env.GITHUB_TOKEN;\n  }\n\n  return runCommand(command, commandArgs, { cwd: options.cwd, env });\n}\n\nfunction runGhJson(args, options = {}) {\n  try {\n    return JSON.parse(runGh(args, options) || 'null');\n  } catch (error) {\n    throw new Error(`gh ${args.join(' ')} returned invalid JSON: ${error.message}`);\n  }\n}\n\nfunction getIssue(repo, issueNumber, options = {}) {\n  const { owner, name } = normalizeRepo(repo);\n  const json = runGhJson([\n    'issue',\n    'view',\n    String(issueNumber),\n    '--repo',\n    `${owner}/${name}`,\n    '--json',\n    'number,title,body,url,state,labels,author,updatedAt,assignees',\n  ], options);\n\n  if (!json) {\n    throw new Error(`Unable to load issue #${issueNumber} from ${repo}`);\n  }","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/github-coordination/gh-api.js#L60-L96","documentation":"runGhJson parses the stdout of a gh command as JSON and wraps any parse failure (or thrown error from runGh) in a message indicating the gh output was not valid JSON. The library expects `gh --json ...` to always emit parseable JSON, so non-JSON output signals an unexpected gh behavior, an error banner mixed into stdout, or a shim producing human-readable text.","triggerScenarios":"Calling runGhJson (via json, getIssue, or listIssues) when gh prints a non-JSON error/warning to stdout, when a custom ECC_GH_SHIM echoes plain text, or when gh output is empty/unexpected for the requested fields.","commonSituations":"Outdated gh versions that don't support a requested --json field, a shim script that prints logging text before the JSON, locale/encoding issues corrupting output, or gh auth prompts being written to stdout.","solutions":["Run the exact `gh ... --json` command manually and inspect its raw output.","Upgrade the GitHub CLI to a version supporting all requested --json fields.","Fix or remove a custom ECC_GH_SHIM so it emits only JSON on stdout.","Re-authenticate gh so it doesn't emit interactive prompts into the output stream."],"exampleFix":"// before\nconst json = runGhJson(['issue', 'view', '123', '-R', 'o/r', '--json', 'newField']);\n// after\n// after upgrading gh to a version supporting 'newField'\nconst json = runGhJson(['issue', 'view', '123', '-R', 'o/r', '--json', 'number,title,state,newField']);","handlingStrategy":"try-catch","validationCode":"const raw = runGh(['issue', 'view', String(n), '-R', repo, '--json', 'number']);\ntry { JSON.parse(raw); } catch (e) { throw new Error(`gh output is not JSON: ${raw.slice(0, 100)}`); }","typeGuard":"const isJsonObject = (v) => v !== null && typeof v === 'object' && !Array.isArray(v);","tryCatchPattern":"try {\n  const json = runGhJson(args);\n} catch (e) {\n  if (e.message.includes('returned invalid JSON')) {\n    console.error('gh emitted non-JSON output; check gh version and ECC_GH_SHIM stdout purity:', e.message);\n  } else { throw e; }\n}","preventionTips":["Keep gh CLI up to date so all --json fields are supported.","Ensure custom shims print ONLY JSON to stdout; logs go to stderr.","Avoid environments where gh writes prompts/banners to stdout.","Test JSON output of gh commands manually when upgrading."],"tags":["json","gh-cli","parsing"],"backgroundTag":"invalid-json-response","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}