{"record":{"id":"976243a6824ae936","repo":"schollz/croc","slug":"github-release-request-failed-response-status","errorCode":null,"errorMessage":"GitHub release request failed (${response.status})","messagePattern":"GitHub release request failed \\((.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"web/src/releases.ts","lineNumber":130,"sourceCode":"  const preferredArchitecture =\n    architecture === \"unknown\"\n      ? platform === \"macOS\"\n        ? \"arm64\"\n        : \"x64\"\n      : architecture;\n  return (\n    assets.find((asset) => assetArchitecture(asset) === preferredArchitecture) ??\n    assets[0]\n  );\n}\n\nexport async function fetchLatestRelease(signal?: AbortSignal) {\n  const response = await fetch(latestReleaseAPI, {\n    signal,\n    headers: { Accept: \"application/vnd.github+json\" },\n  });\n  if (!response.ok) {\n    throw new Error(`GitHub release request failed (${response.status})`);\n  }\n  const release = (await response.json()) as GitHubRelease;\n  if (\n    !release.tag_name ||\n    !release.html_url ||\n    !Array.isArray(release.assets)\n  ) {\n    throw new Error(\"GitHub returned invalid release metadata\");\n  }\n  return release;\n}\n","sourceCodeStart":112,"sourceCodeEnd":142,"githubUrl":"https://github.com/schollz/croc/blob/e25f1bdc04f07f094d50b0a1bf67e2563944b57a/web/src/releases.ts#L112-L142","documentation":"Thrown by fetchLatestRelease() when the GitHub API request for the latest release completes with a non-ok HTTP status; the status code is embedded in the message. It distinguishes transport success from API failure before the response body is parsed as a release.","triggerScenarios":"Calling fetchLatestRelease() when api.github.com returns 403 (unauthenticated rate limit of 60 req/hr/IP exhausted), 404 (repo or release missing), or a 5xx.","commonSituations":"CI pipelines polling the endpoint frequently; many users behind one NAT/proxy egress IP; GitHub incidents; repository renamed so the API 404s.","solutions":["On 403, back off respecting X-RateLimit-Reset or add an Authorization header / GITHUB_TOKEN to raise the limit","On 404, verify the repository and that a published (non-draft) release exists","Cache the last successful release response and serve stale on failure","Retry with exponential backoff for transient 5xx"],"exampleFix":"// before\nconst release = await fetchLatestRelease(signal);\n\n// after\nlet release;\ntry {\n  release = await fetchLatestRelease(signal);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('(403)')) release = lastGoodRelease;\n  else throw e;\n}","handlingStrategy":"retry","validationCode":"async function releaseEndpointHealthy(signal?: AbortSignal): Promise<boolean> {\n  const r = await fetch(latestReleaseAPI, { method: 'HEAD', signal });\n  return r.ok;\n}","typeGuard":null,"tryCatchPattern":"try { return await fetchLatestRelease(signal); } catch (e) { if (e instanceof Error && /\\(403\\)/.test(e.message)) return lastGoodRelease; if (e instanceof Error && /\\(5\\d\\d\\)/.test(e.message)) return retryWithBackoff(() => fetchLatestRelease(signal), 3); throw e; }","preventionTips":["Cache the last good release payload and serve it stale on failure","Add a GitHub token in CI / shared-IP environments; honor X-RateLimit-Reset before retrying"],"tags":["github-api","http","rate-limit","network"],"backgroundTag":null,"analyzedSha":"e25f1bdc04f07f094d50b0a1bf67e2563944b57a","analyzedAt":"2026-08-15T12:53:39.096Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}