{"record":{"id":"46ed7f27806fab80","repo":"stablyai/orca","slug":"github-releases-response-page-page-for-repo-46ed7f","errorCode":null,"errorMessage":"GitHub releases response page ${page} for ${repo} was not an array","messagePattern":"GitHub releases response page (.+?) for (.+?) was not an array","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"config/scripts/latest-stable-release.mjs","lineNumber":63,"sourceCode":"}\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\n    )\n    if (!Array.isArray(pageReleases)) {\n      throw new Error(`GitHub releases response page ${page} for ${repo} was not an array`)\n    }\n\n    releases.push(...pageReleases)\n    if (pageReleases.length < 100) {\n      break\n    }\n  }\n\n  return releases\n}\n\nasync function main() {\n  const token = process.env.GH_TOKEN || process.env.GITHUB_TOKEN\n  const repo = process.env.GITHUB_REPOSITORY || 'stablyai/orca'\n  const releases = await fetchReleases(repo, token)\n  process.stdout.write(latestStableDesktopReleaseTag(releases))\n}\n","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/config/scripts/latest-stable-release.mjs#L45-L81","documentation":"fetchReleases paginates /releases with per_page=100 and expects each page to be a JSON array. It throws when a page response is not an array, surfacing the page number and repo. A non-array page indicates the API returned an error object, a rate-limit document, or an unexpected shape rather than the release list, so continuing to paginate would be wrong.","triggerScenarios":"GitHub returns a 200 with a non-array body (rare, e.g. an API gateway error document or an abuse-rate-limit object); a proxy/interceptor rewrites the response; the endpoint contract changes.","commonSituations":"An enterprise/proxy returning an HTML or object error body with status 200; an API change after a GitHub API version bump; a rate-limit response that still carries 200.","solutions":["Inspect the response body that preceded the throw (the message includes page and repo; capture the body separately to diagnose).","Verify the token and rate-limit status, since some non-array 200s are rate-limit related.","Confirm X-GitHub-Api-Version still matches the supported API version.","Handle the non-array page in the caller instead of treating it as a hard failure."],"exampleFix":"// before\nif (!Array.isArray(pageReleases)) {\n  throw new Error(`GitHub releases response page ${page} for ${repo} was not an array`)\n}\n\n// after — capture the body for diagnosis before failing\nif (!Array.isArray(pageReleases)) {\n  throw new Error(`GitHub releases response page ${page} for ${repo} was not an array; body=${JSON.stringify(pageReleases).slice(0, 300)}`)\n}","handlingStrategy":"try-catch","validationCode":"const sample = await githubJson(fetchImpl, urlPage1, token)\nif (!Array.isArray(sample)) {\n  throw new Error(`Unexpected releases shape for ${repo}: ${JSON.stringify(sample).slice(0,300)}`)\n}","typeGuard":"function isReleaseArray(value: unknown): value is unknown[] {\n  return Array.isArray(value)\n}","tryCatchPattern":"try {\n  releases = await fetchReleases(repo, token)\n} catch (err) {\n  if (/was not an array/.test(err.message)) {\n    log.warn(`GitHub returned a non-array releases page for ${repo}; possible rate limit or proxy`)\n  }\n  throw err\n}","preventionTips":["Capture the raw body alongside the page number so non-array 200s are diagnosable.","Be wary of proxies/enterprise gateways that rewrite GitHub responses."],"tags":["github-api","validation"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}