{"record":{"id":"8a2a52038ee3cd03","repo":"stablyai/orca","slug":"token-is-required-8a2a52","errorCode":null,"errorMessage":"token is required","messagePattern":"token is required","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"config/scripts/publish-complete-draft-releases.mjs","lineNumber":88,"sourceCode":"  if (!Array.isArray(releases)) {\n    throw new Error(`GitHub releases response for ${repo} was not an array`)\n  }\n  return releases\n}\n\nexport async function publishCompleteDraftReleases({\n  repo,\n  token,\n  fetchImpl = fetch,\n  verifyReleaseAssets = verifyRequiredReleaseAssets,\n  isDraftBuiltFromCurrentRef = ({ tag }) => isTagBuiltFromCurrentRef(tag),\n  log = console.log\n}) {\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 = await fetchReleases(repo, token, fetchImpl)\n  const candidates = releases\n    .filter(isReleaseCutDraft)\n    .sort((a, b) => new Date(a.created_at ?? 0).getTime() - new Date(b.created_at ?? 0).getTime())\n\n  const published = []\n  const skipped = []\n\n  for (const release of candidates) {\n    const tag = release.tag_name\n    if (!(await Promise.resolve(isDraftBuiltFromCurrentRef({ tag, release })))) {\n      const reason = 'tag is not built from the current release ref'\n      skipped.push({ tag, reason })\n      log(`Skipping stale RC draft release ${tag}: ${reason}`)\n      continue\n    }","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/config/scripts/publish-complete-draft-releases.mjs#L70-L106","documentation":"Thrown by publishCompleteDraftReleases in config/scripts/publish-complete-draft-releases.mjs when the `token` option is falsy. The token is sent as `Authorization: Bearer ${token}` on every GitHub request by githubJson, so an empty token yields anonymous calls that 401 on private repos or rate-limit instantly. The guard at line 87-88 runs before fetchReleases.","triggerScenarios":"Call publishCompleteDraftReleases without a token, or run the CLI with neither GH_TOKEN nor GITHUB_TOKEN set in the environment. main() at line 159 sets `token = process.env.GH_TOKEN || process.env.GITHUB_TOKEN`, so both being unset/empty trips the guard.","commonSituations":"A GitHub Actions workflow forgot to pass the `GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}` env, a local run has no token exported, or a fine-grained PAT was cleared. The error appears before any network call, so it is the first thing to fail in a misconfigured release job.","solutions":["Set GH_TOKEN (preferred) or GITHUB_TOKEN to a valid PAT or the Actions GITHUB_TOKEN before running.","If calling the API directly, pass `token` in the options object.","Verify the token has `contents:write` scope for the target repo."],"exampleFix":"// before\n# no token exported\nnode config/scripts/publish-complete-draft-releases.mjs\n\n// after\nGH_TOKEN=ghp_xxx node config/scripts/publish-complete-draft-releases.mjs","handlingStrategy":"validation","validationCode":"const token = process.env.GH_TOKEN || process.env.GITHUB_TOKEN\nif (!token) throw new Error('Set GH_TOKEN or GITHUB_TOKEN before running the release publisher')","typeGuard":"function hasToken(env = process.env) {\n  return Boolean(env.GH_TOKEN || env.GITHUB_TOKEN)\n}","tryCatchPattern":null,"preventionTips":["In GitHub Actions, map `GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}` into env.","For local runs, export GH_TOKEN from a PAT with `contents:write`.","Fail fast on missing token in your wrapper before any network call."],"tags":["api","auth","github","release","validation"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}