tinyhumansai/openhuman · error · Error
gh api PATCH failed: ${r.stderr?.trim() || ""}
Error message
gh api PATCH failed: ${r.stderr?.trim() || ""} What it means
postOrUpdateTrackingComment() in scripts/agent-batch/status.mjs updates the previously-found tracking comment via `gh api --method PATCH repos/<repo>/issues/comments/<id> -F body=@-` (body on stdin to dodge ARG_MAX) and throws with gh's stderr on non-zero exit. This branch runs when the comment listing DID find a comment carrying the <!-- batch:<id> --> marker, and patches it in place with the freshly rendered table.
Source
Thrown at scripts/agent-batch/status.mjs:183
} else {
const id = existing[0].id;
// Pass the comment body via stdin (-F body=@-) rather than a command-line
// arg. Long markdown tables can grow large and -f body=${body} risks
// hitting OS argv length limits (ARG_MAX).
const r = spawnSync(
"gh",
[
"api",
"--method",
"PATCH",
`repos/${spec.base_repo}/issues/comments/${id}`,
"-F",
"body=@-",
],
{ encoding: "utf8", input: body },
);
if (r.status !== 0) {
throw new Error(`gh api PATCH failed: ${r.stderr?.trim() || ""}`);
}
process.stdout.write(
`[agent-batch] updated tracking comment ${existing[0].html_url}\n`,
);
}
}
function main() {
const { positional, flags } = parseArgs(process.argv.slice(2));
if (flags.help || flags.h || flags["?"]) {
process.stdout.write(`${usage()}\n`);
process.exit(0);
}
const specPath = positional[0];
if (!specPath) {
process.stderr.write(`${usage()}\n`);
process.exit(2);
}View on GitHub (pinned to a221052e0d)
Solutions
- Re-run the command — if the comment was deleted, the listing step now finds none and the script posts a fresh comment instead of PATCHing
- Check the token has issues:write permission on the target repo (`gh auth status`)
- Delete the orphaned marker comment yourself if you intentionally removed the old one, so the next run starts clean at the post path
- Space out concurrent --post invocations to avoid racing the same comment id
Example fix
# before $ node scripts/agent-batch/status.mjs batch.json --post Error: gh api PATCH failed: HTTP 404: Not Found # after (comment was deleted; re-run posts a new one) $ node scripts/agent-batch/status.mjs batch.json --post [agent-batch] posted new tracking comment on #1234
Defensive patterns
Strategy: retry
Validate before calling
// Re-verify the comment still exists right before patching
const check = spawnSync("gh", ["api", `repos/${spec.base_repo}/issues/comments/${id}`], { encoding: "utf8" });
if (check.status !== 0) {
// comment vanished — fall back to the post path instead of PATCHing
return postNewComment(spec, body);
} Try / catch
try {
await patchComment(id, body);
} catch (e) {
if (/gh api PATCH failed/.test(e.message) && /404/.test(e.message)) {
return postNewComment(spec, body); // deleted comment → post a fresh one
}
if (/rate limit/i.test(e.message)) { await sleep(30_000); return patchComment(id, body); }
throw e;
} Prevention
- Treat PATCH-404 as a signal to re-list and re-post, not as a hard failure
- When deleting tracking comments manually, delete ALL marker comments for the batch so the next --post regenerates cleanly
- Serialize --post runs (lockfile or CI job) so two writers never race the same comment id
When it happens
Trigger: A --post run where the comment id captured from the listing step no longer exists at PATCH time (someone deleted the tracking comment between the list and the patch), the token lacks issues:write, or a rate limit/network error hits the PATCH. The id comes from existing[0].id, so two humans running --post concurrently against the same batch can also race one comment out of existence.
Common situations: Maintainers deleting a stale tracking comment while an automated status loop is mid-update; read-only tokens reaching the PATCH stage because the earlier listing only needed read; primary/secondary rate limits during long-lived monitoring.
Related errors
- gh failed (${r.status}): ${r.stderr?.trim() || "unknown erro
- gh api failed (${list.status}): ${list.stderr?.trim() || "un
- gh issue comment failed: ${r.stderr?.trim() || ""}
- could not resolve repo (set RABBIT_REPO=owner/name)
- OpenHuman could not reach its local runtime. Quit and reopen
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/a0bb5d4aa8d3eb45.
Report an issue: GitHub.