{"record":{"id":"eb54f0f7859cfcba","repo":"stablyai/orca","slug":"github-request-failed-res-status-res-statuste-eb54f0","errorCode":null,"errorMessage":"GitHub request failed ${res.status} ${res.statusText}: ${body.slice(0, 300)}","messagePattern":"GitHub request failed (.+?) (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"config/scripts/latest-stable-release.mjs","lineNumber":42,"sourceCode":"    .filter((release) => release?.draft !== true)\n    .map((release) => parseDesktopStableTag(release?.tag_name ?? release?.tagName ?? ''))\n    .filter(Boolean)\n    .sort((a, b) => a.major - b.major || a.minor - b.minor || a.patch - b.patch)\n\n  return stableTags.at(-1)?.tag ?? ''\n}\n\nasync function githubJson(fetchImpl, url, token) {\n  const res = await fetchImpl(url, {\n    headers: {\n      Accept: 'application/vnd.github+json',\n      Authorization: `Bearer ${token}`,\n      'X-GitHub-Api-Version': API_VERSION\n    }\n  })\n  if (!res.ok) {\n    const body = await res.text().catch(() => '')\n    throw new Error(`GitHub request failed ${res.status} ${res.statusText}: ${body.slice(0, 300)}`)\n  }\n  return res.json()\n}\n\nexport async function fetchReleases(repo, token, fetchImpl = fetch) {\n  if (!repo) {\n    throw new Error('repo is required')\n  }\n  if (!token) {\n    throw new Error('token is required')\n  }\n\n  const releases = []\n  for (let page = 1; ; page += 1) {\n    const pageReleases = await githubJson(\n      fetchImpl,\n      `https://api.github.com/repos/${repo}/releases?per_page=100&page=${page}`,\n      token","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/config/scripts/latest-stable-release.mjs#L24-L60","documentation":"githubJson performs an authenticated GitHub API request (Bearer token, X-GitHub-Api-Version 2022-11-28) and throws when the response is not ok (non-2xx). The message includes status, statusText, and the first 300 chars of the body so the caller can see the GitHub error message without logging the full payload.","triggerScenarios":"Missing/invalid/expired token (401/403); rate or secondary rate limit (403/429); repo not found or no access (404); GitHub server error (5xx); wrong API version header.","commonSituations":"GH_TOKEN/GITHUB_TOKEN not injected in CI or expired; token lacking repo read scope; rate limit exhausted by other jobs; GITHUB_REPOSITORY pointing at a private fork the token can't read.","solutions":["Verify the token is set, valid, and has the needed scopes (repo / public_repo).","Check the rate limit with 'gh api rate_limit' and back off if near the ceiling.","Confirm the repo slug is correct and accessible to the token.","Retry on 5xx with exponential backoff."],"exampleFix":"// before\nconst releases = await fetchReleases(repo, token)\n\n// after\nif (!token) throw new Error('GH_TOKEN required')\nlet releases\ntry {\n  releases = await fetchReleases(repo, token)\n} catch (err) {\n  throw new Error(`Could not fetch releases for ${repo}: ${err.message}`)\n}","handlingStrategy":"try-catch","validationCode":"if (!token) throw new Error('GitHub token is required')\nif (!repo || !/^[^/\\s]+\\/[^/\\s]+$/.test(repo)) throw new Error(`Invalid repo slug: ${repo}`)","typeGuard":null,"tryCatchPattern":"try {\n  releases = await fetchReleases(repo, token)\n} catch (err) {\n  if (/401|403/.test(err.message)) throw new Error(`Auth failed for ${repo}; check token scopes`)\n  if (/429|rate limit/i.test(err.message)) throw new Error(`Rate limited; back off and retry`)\n  throw err\n}","preventionTips":["Inject a fresh, scoped GH_TOKEN in CI and check rate_limit before large paginated calls.","Confirm the repo slug is correct and that the token can read it."],"tags":["github-api","network","auth"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}