{"record":{"id":"7547aa68c57bd636","repo":"tinyhumansai/openhuman","slug":"gh-api-failed-list-status-list-stderr-tri","errorCode":null,"errorMessage":"gh api failed (${list.status}): ${list.stderr?.trim() || \"unknown error\"}","messagePattern":"gh api failed \\((.+?)\\): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/agent-batch/status.mjs","lineNumber":136,"sourceCode":"\nfunction postOrUpdateTrackingComment(spec, body) {\n  const issue = spec.tracking_issue;\n  const list = spawnSync(\n    \"gh\",\n    [\n      \"api\",\n      `repos/${spec.base_repo}/issues/${issue}/comments`,\n      \"--paginate\",\n      \"--jq\",\n      // Emit one object per line. `gh api --paginate` runs the jq filter\n      // per-page; wrapping in `[...]` would produce concatenated array\n      // fragments that aren't valid JSON. NDJSON sidesteps that.\n      `.[] | select(.body | contains(\"${COMMENT_MARKER(spec.batch_id)}\")) | {id, html_url}`,\n    ],\n    { encoding: \"utf8\" },\n  );\n  if (list.status !== 0) {\n    throw new Error(\n      `gh api failed (${list.status}): ${list.stderr?.trim() || \"unknown error\"}`,\n    );\n  }\n  const existing = (list.stdout || \"\")\n    .split(\"\\n\")\n    .map((line) => line.trim())\n    .filter((line) => line.length > 0)\n    .map((line) => JSON.parse(line));\n  if (existing.length === 0) {\n    const r = spawnSync(\n      \"gh\",\n      [\n        \"issue\",\n        \"comment\",\n        String(issue),\n        \"--repo\",\n        spec.base_repo,\n        \"--body-file\",","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/scripts/agent-batch/status.mjs#L118-L154","documentation":"postOrUpdateTrackingComment() in scripts/agent-batch/status.mjs calls `gh api repos/<repo>/issues/<tracking_issue>/comments --paginate --jq '<filter>'` to find the existing batch tracking comment (matched by the <!-- batch:<id> --> marker) and throws on non-zero exit with gh's stderr. This is the read half of the --post flow; failure here means the script can neither find nor update the tracking comment.","triggerScenarios":"Running status.mjs with --post when: no credentials for the REST API (401), the token lacks repo scope for a private repo (403/404), the tracking_issue number in the spec does not exist (404), secondary-rate-limit or network errors, or the gh api invocation itself fails (old gh version without --paginate/--jq support). The jq filter interpolates the batch_id, but validateSpec() constrains batch_id to a kebab-case slug, so filter injection is not a realistic cause.","commonSituations":"Fine-grained PATs granted only PR-read but not issues-read; spec's tracking_issue pointing at an issue in a different repo or deleted between runs; gh upgraded/downgraded around the --jq per-page behavior; intermittent GitHub API 5xx during batch monitoring loops.","solutions":["Run the same call manually to see the real error: `gh api repos/tinyhumansai/openhuman/issues/<N>/comments --limit 1`","Check `gh auth status` and the token's scopes — issues read access on the target repo is required","Verify spec.tracking_issue exists in tinyhumansai/openhuman and is an issue (not a discussion/PR-only number)","Upgrade gh to a current version (needs --paginate and --jq), then re-run"],"exampleFix":"# before\n$ node scripts/agent-batch/status.mjs batch.json --post\nError: gh api failed (1): HTTP 404: Not Found\n\n# after (fix tracking_issue in batch.json to a real issue, then)\n$ node scripts/agent-batch/status.mjs batch.json --post\n[agent-batch] posted new tracking comment on #1234","handlingStrategy":"retry","validationCode":"// Pre-flight: the exact REST call the script makes, minus pagination\nimport { spawnSync } from \"node:child_process\";\nconst r = spawnSync(\"gh\", [\"api\", `repos/tinyhumansai/openhuman/issues/${issueNumber}/comments`, \"--limit\", \"1\"], { encoding: \"utf8\" });\nif (r.status !== 0) throw new Error(`cannot list comments on #${issueNumber}: ${r.stderr}`);","typeGuard":null,"tryCatchPattern":"try {\n  postOrUpdateTrackingComment(spec, body);\n} catch (e) {\n  if (/gh api failed \\((\\d+)\\)/.test(e.message) && /rate limit|5\\d\\d|ECONN/i.test(e.message)) {\n    await sleep(30_000);\n    postOrUpdateTrackingComment(spec, body); // one retry; a fresh listing re-resolves the comment id\n    return;\n  }\n  throw e;\n}","preventionTips":["Validate spec.tracking_issue exists (a cheap gh api issues/N probe) before starting a long batch","Pin a gh version in CI so --paginate/--jq behavior doesn't drift under you","On retry, always re-run the listing step — never PATCH a stale comment id"],"tags":["github","cli","network","auth"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}