{"record":{"id":"e9d0f880714fb93b","repo":"stablyai/orca","slug":"github-releases-response-page-page-for-repo","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/create-draft-release.mjs","lineNumber":91,"sourceCode":"    }\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\nasync function fetchRepoReleases(repo, token, fetchImpl) {\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    releases.push(...pageReleases)\n    if (pageReleases.length < 100) {\n      break\n    }\n  }\n  return releases\n}\n\nexport function truncateReleaseBody(body, maxLength = MAX_RELEASE_BODY_LENGTH) {\n  if (body.length <= maxLength) {\n    return body\n  }\n\n  const availableLength = maxLength - TRUNCATION_NOTICE.length\n  if (availableLength <= 0) {\n    throw new Error('Release truncation notice is longer than the maximum release body length')\n  }","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/config/scripts/create-draft-release.mjs#L73-L109","documentation":"Thrown by fetchRepoReleases when a paginated GitHub releases response succeeds (res.ok) but the parsed JSON is not an Array. GitHub's releases endpoint normally returns an array; a non-array 2xx body indicates an unexpected API/proxy shape (create-draft-release.mjs:82-99).","triggerScenarios":"A corporate proxy or GitHub Enterprise gateway returning a wrapped object instead of a raw array; GitHub returning an error envelope that still carries a 2xx status (rare); a mocked fetchImpl in tests returning { releases: [...] } instead of [...].","commonSituations":"Test mocks that wrap the response in an object; GitHub Enterprise Server versions with non-standard response shapes; a man-in-the-middle proxy rewriting JSON; pointing the script at a non-GitHub-compatible API.","solutions":["If using a custom fetchImpl (e.g., in tests), ensure it returns a raw array for the releases endpoint, matching the real GitHub API.","Verify the script runs against api.github.com or a compatible GitHub Enterprise endpoint.","Inspect the actual response body to confirm whether a proxy is wrapping it."],"exampleFix":"// before (test mock returning wrapped object)\nfetchImpl = async () => ({ ok: true, json: async () => ({ releases: [] }) })\n// after (mock returns a raw array)\nfetchImpl = async () => ({ ok: true, json: async () => [] })","handlingStrategy":"type-guard","validationCode":"async function releasesAreArray(repo, token, fetchImpl = fetch) {\n  const res = await fetchImpl(\n    `https://api.github.com/repos/${repo}/releases?per_page=1`,\n    { headers: { Authorization: `Bearer ${token}`, Accept: 'application/vnd.github+json' } }\n  )\n  if (!res.ok) return false\n  return Array.isArray(await res.json())\n}","typeGuard":"function isReleasesArray(body) {\n  return Array.isArray(body)\n}","tryCatchPattern":null,"preventionTips":["In tests, ensure the fetchImpl mock returns a raw array for the releases endpoint.","Confirm the target is the standard GitHub releases API (array), not a wrapped Enterprise/proxy shape."],"tags":["network","github-api","release","data-validation"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}