{"record":{"id":"3d83578c3c18f907","repo":"oven-sh/bun","slug":"github-p-r-status-r-statustext","errorCode":null,"errorMessage":"github ${p}: ${r.status} ${r.statusText}","messagePattern":"github (.+?): (.+?) (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/binary-size.ts","lineNumber":266,"sourceCode":"\nfunction fmtBytes(n: number): string {\n  return `${(n / 1024 / 1024).toFixed(2)} MB`;\n}\nfunction fmtDelta(n: number): string {\n  const sign = n >= 0 ? \"+\" : \"-\";\n  const abs = Math.abs(n);\n  return abs >= 1024 * 1024 ? `${sign}${(abs / 1024 / 1024).toFixed(2)} MB` : `${sign}${(abs / 1024).toFixed(1)} KB`;\n}\n\n// ─── local mode: canary vs latest tagged release ───\n\ntype GithubRelease = { tag_name: string; assets: { name: string; browser_download_url: string }[] };\n\nasync function compareGithubReleases() {\n  const auth = process.env.GITHUB_TOKEN ? { Authorization: `Bearer ${process.env.GITHUB_TOKEN}` } : undefined;\n  const gh = (p: string) =>\n    fetch(`https://api.github.com/repos/oven-sh/bun/${p}`, { headers: auth }).then(r => {\n      if (!r.ok) throw new Error(`github ${p}: ${r.status} ${r.statusText}`);\n      return r.json() as Promise<GithubRelease>;\n    });\n\n  const [latest, canary] = await Promise.all([gh(\"releases/latest\"), gh(\"releases/tags/canary\")]);\n\n  // The release zips we care about are the stripped runtime binaries:\n  // bun-<os>-<arch>[-musl][-baseline].zip. Skip -profile (unstripped) and\n  // anything that isn't a single-binary zip.\n  const isBinaryZip = (n: string) => /^bun-[a-z0-9-]+\\.zip$/.test(n) && !n.includes(\"-profile\");\n  const assetMap = (r: GithubRelease) =>\n    new Map(r.assets.filter(a => isBinaryZip(a.name)).map(a => [a.name.replace(/\\.zip$/, \"\"), a.browser_download_url]));\n\n  const latestAssets = assetMap(latest);\n  const canaryAssets = assetMap(canary);\n  const triplets = [...latestAssets.keys()].filter(t => canaryAssets.has(t)).sort();\n\n  process.stderr.write(`Reading ${triplets.length} zips from each of ${latest.tag_name} and canary…\\n`);\n  const [latestSizes, canarySizes] = await Promise.all([","sourceCodeStart":248,"sourceCodeEnd":284,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/scripts/binary-size.ts#L248-L284","documentation":"The gh() helper inside compareGithubReleases() (local mode of scripts/binary-size.ts) throws when fetching releases/latest or releases/tags/canary from api.github.com returns non-2xx. status + statusText distinguish rate limiting (403) from a missing release (404).","triggerScenarios":"No GITHUB_TOKEN in the local environment with the anonymous 60 req/h quota exhausted (403); the canary tag or latest release temporarily absent while release automation is mid-publish (404); GitHub 5xx.","commonSituations":"Running bun scripts/binary-size.ts locally for a canary-vs-latest comparison without auth; running exactly while the release pipeline is publishing and tags are in flux.","solutions":["export GITHUB_TOKEN=$(gh auth token) before running","On 404 for canary: wait for release automation to finish publishing and re-run","On 403: wait out the rate-limit window or authenticate"],"exampleFix":"# before\n$ bun scripts/binary-size.ts\nError: github releases/tags/canary: 404\n\n# after\n$ export GITHUB_TOKEN=$(gh auth token)\n$ bun scripts/binary-size.ts","handlingStrategy":"retry","validationCode":"if (!process.env.GITHUB_TOKEN) {\n  console.warn(\"no GITHUB_TOKEN — anonymous GitHub rate limit is 60/h, gh() may fail\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  await compareGithubReleases();\n} catch (e) {\n  if (/github releases\\/.*: 404/.test(String(e?.message))) {\n    console.error(\"canary/latest release missing — publish may be in flight, retry shortly\");\n  }\n  throw e;\n}","preventionTips":["Authenticate all local runs that touch api.github.com","Avoid racing the release pipeline when comparing canary"],"tags":["github-api","network","binary-size","local-dev"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}