{"record":{"id":"5c2fca46d7165a98","repo":"oven-sh/bun","slug":"github-api-request-failed-response-status-re","errorCode":null,"errorMessage":"GitHub API request failed: ${response.status} ${response.statusText}","messagePattern":"GitHub API request failed: (.+?) (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/auto-close-duplicates.ts","lineNumber":91,"sourceCode":"  // Handle rate limit errors with retry\n  if (response.status === 429 || response.status === 403) {\n    if (retryCount >= maxRetries) {\n      throw new Error(`GitHub API rate limit exceeded after ${maxRetries} retries`);\n    }\n\n    const retryAfter = response.headers.get(\"retry-after\");\n    const waitTime = retryAfter ? parseInt(retryAfter) * 1000 : Math.min(1000 * Math.pow(2, retryCount), 32000);\n\n    console.warn(\n      `[WARNING] Rate limited (${response.status}), retry ${retryCount + 1}/${maxRetries} after ${waitTime}ms`,\n    );\n    await sleep(waitTime);\n\n    return githubRequest<T>(endpoint, token, method, body, retryCount + 1);\n  }\n\n  if (!response.ok) {\n    throw new Error(`GitHub API request failed: ${response.status} ${response.statusText}`);\n  }\n\n  return response.json();\n}\n\nasync function fetchAllComments(\n  owner: string,\n  repo: string,\n  issueNumber: number,\n  token: string,\n): Promise<GitHubComment[]> {\n  const allComments: GitHubComment[] = [];\n  let page = 1;\n  const perPage = 100;\n\n  while (true) {\n    const comments: GitHubComment[] = await githubRequest(\n      `/repos/${owner}/${repo}/issues/${issueNumber}/comments?per_page=${perPage}&page=${page}`,","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/scripts/auto-close-duplicates.ts#L73-L109","documentation":"Generic non-OK response from the GitHub REST call after the rate-limit branch (429/403) did not match. The message includes status and statusText only, so the response body with the actual GitHub error (message, documentation_url) is lost.","triggerScenarios":"401 from an invalid/expired token; 404 from a wrong endpoint or missing repo; 422 validation errors on POST bodies; GitHub 5xx outside the retry path.","commonSituations":"Expired GITHUB_TOKEN in a long-lived context; typo'd repo/issue number; GraphQL/REST shape mismatch in a POST payload.","solutions":["Include the response body in the thrown error to see GitHub's own message and documentation_url","Verify token validity and scopes for the endpoint being called","Check owner/repo/issue numbers passed to the endpoint"],"exampleFix":"// before\nif (!response.ok) {\n  throw new Error(`GitHub API request failed: ${response.status} ${response.statusText}`);\n}\n\n// after\nif (!response.ok) {\n  const body = await response.text();\n  throw new Error(`GitHub API request failed: ${response.status} ${response.statusText} ${body.slice(0, 300)}`);\n}","handlingStrategy":"retry","validationCode":"null","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Surface the response body in errors so 4xx causes are diagnosable","Retry only idempotent GETs automatically; fail fast on 4xx POST payloads","Validate token scopes and endpoint paths before long batch runs"],"tags":["github-api","http","api"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}