{"record":{"id":"4a3d60da40a9847a","repo":"thedotmack/claude-mem","slug":"could-not-parse-label-json-message","errorCode":null,"errorMessage":"Could not parse ${label} JSON: ${message}","messagePattern":"Could not parse (.+?) JSON: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/pr-babysit-status.ts","lineNumber":124,"sourceCode":"  }\n}\n\nfunction runGh(args: string[], options: { allowExitCodes?: number[] } = {}): string {\n  const result = runCommand(['gh', ...args]);\n  const allowed = new Set([0, ...(options.allowExitCodes ?? [])]);\n  if (!allowed.has(result.exitCode)) {\n    const detail = result.stderr || result.stdout || `exit code ${result.exitCode}`;\n    throw new Error(`gh ${args.join(' ')} failed: ${detail}`);\n  }\n  return result.stdout;\n}\n\nfunction parseJson<T>(raw: string, label: string): T {\n  try {\n    return JSON.parse(raw) as T;\n  } catch (error) {\n    const message = error instanceof Error ? error.message : String(error);\n    throw new Error(`Could not parse ${label} JSON: ${message}`);\n  }\n}\n\nfunction checkPrerequisites() {\n  const git = runCommand(['git', 'rev-parse', '--is-inside-work-tree']);\n  if (git.exitCode !== 0 || git.stdout.trim() !== 'true') {\n    throw new Error('Not in a git repository. Run this from a checked-out repo.');\n  }\n\n  const ghVersion = runCommand(['gh', '--version']);\n  if (ghVersion.exitCode !== 0) {\n    throw new Error('GitHub CLI is not available. Install gh and try again.');\n  }\n\n  const auth = runCommand(['gh', 'auth', 'status']);\n  if (auth.exitCode !== 0) {\n    throw new Error(`GitHub CLI is not authenticated. Run \"gh auth login\".\\n${auth.stderr || auth.stdout}`.trim());\n  }","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d768ba364302d12b76e69e4f021f0bb1d2d50ed6/scripts/pr-babysit-status.ts#L106-L142","documentation":"Thrown by parseJson() when JSON.parse fails on output returned by runGh(). It labels which logical payload failed ('pull request', 'checks', 'reviews', etc.) so the caller knows which gh call produced unparseable text. This guards every JSON-expecting gh result in the script.","triggerScenarios":"gh emitted a non-JSON string before its JSON (e.g. a warning on stderr merged into stdout, a deprecation notice, an interactive prompt). An empty stdout where parseJson was still called. A gh version that changes the --json shape. A network glitch truncating paginated output mid-array.","commonSituations":"gh updated to a version that prepends a banner. gh api --paginate interleaving records in a way that isn't a clean JSON array. Running in an environment where gh prints update notifications to stdout. A repo so large that paginated reviews exceed memory and produce partial output.","solutions":["Reproduce by running the exact gh command (shown via the label and the failing call site) and inspect its raw stdout.","Suppress gh noise: ensure GH_NO_UPDATE_NOTIFIER or run with a quiet/known gh version.","If stdout is empty, guard parseJson callers to skip when raw is falsy (the checks path already does `raw ? parseJson(...) : []`).","If pagination is the cause, switch from --paginate to an explicit loop with a per-page parse."],"exampleFix":"// before — always parse even when gh printed nothing\nreturn parseJson<CheckRun[]>(runGh([...]), 'checks')\n// after — skip parse on empty output\nconst raw = runGh([...], { allowExitCodes: [GH_PENDING_EXIT_CODE] })\nreturn raw ? parseJson<CheckRun[]>(raw, 'checks') : []","handlingStrategy":"validation","validationCode":"function tryParse<T>(raw: string, label: string): T | null {\n  try { return JSON.parse(raw) as T; } catch { return null; }\n}\n// skip when raw is empty\nconst data = raw ? tryJson<T>(raw, 'checks') : [];","typeGuard":"function looksLikeJson(s: string): boolean {\n  const t = s.trim();\n  return t.startsWith('{') || t.startsWith('[');\n}","tryCatchPattern":"try {\n  return parseJson<T>(raw, label);\n} catch (e) {\n  if (e instanceof Error && /Could not parse/.test(e.message)) {\n    console.error(`gh produced non-JSON for ${label}:`, raw.slice(0, 200));\n  }\n  throw e;\n}","preventionTips":["Suppress gh update banners and noise that can leak into stdout (GH_NO_UPDATE_NOTIFIER).","Guard parseJson callers to skip parsing when stdout is empty.","Pin a known gh version in CI so output shape is stable."],"tags":["json","parsing","github","gh"],"backgroundTag":null,"analyzedSha":"d768ba364302d12b76e69e4f021f0bb1d2d50ed6","analyzedAt":"2026-08-12T23:52:55.241Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}