{"record":{"id":"af5631887db53856","repo":"stablyai/orca","slug":"release-repo-tag-was-not-found-in-the-draft","errorCode":null,"errorMessage":"Release ${repo}@${tag} was not found in the draft-aware releases list","messagePattern":"Release (.+?)@(.+?) was not found in the draft-aware releases list","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"config/scripts/verify-release-required-assets.mjs","lineNumber":74,"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\n}\n\nasync function fetchRelease(repo, tag, token) {\n  // The publish gate runs while the release is still draft.\n  const res = await githubFetch(`https://api.github.com/repos/${repo}/releases?per_page=100`, token)\n  const releases = await res.json()\n  if (!Array.isArray(releases)) {\n    throw new Error(`GitHub releases response for ${repo} was not an array`)\n  }\n  const release = releases.find((candidate) => candidate.tag_name === tag)\n  if (!release) {\n    throw new Error(`Release ${repo}@${tag} was not found in the draft-aware releases list`)\n  }\n  return release\n}\n\nasync function fetchAssetText(repo, asset, token) {\n  const res = await githubFetch(\n    `https://api.github.com/repos/${repo}/releases/assets/${asset.id}`,\n    token,\n    'application/octet-stream'\n  )\n  return res.text()\n}\n\nexport async function verifyRequiredReleaseAssets({ repo, tag, token }) {\n  const release = await fetchRelease(repo, tag, token)\n  const assetsByName = new Map(release.assets.map((asset) => [asset.name, asset]))\n\n  const requiredNames = new Set(getRequiredReleaseAssetNames(tag))","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/config/scripts/verify-release-required-assets.mjs#L56-L92","documentation":"Thrown by fetchRelease() when the GitHub Releases API returns a valid array of releases but none has a tag_name matching the requested tag. The script deliberately lists releases (not the single-release endpoint) because the publish gate runs while the release is still in draft state, and the single endpoint hides drafts. So this fires when the tag genuinely has no release object yet — draft or otherwise — within the first 100 releases returned.","triggerScenarios":"Calling verify-release-required-assets.mjs with a tag whose GitHub Release has not been created yet; the release exists as a git tag but the GitHub Releases object was never authored; the release sits beyond the 100-item per_page window on a repo with many releases; a typo'd tag that doesn't match any candidate.tag_name.","commonSituations":"Running the asset-verification gate before the release-create step of the workflow has finished; tag name casing/format mismatch (e.g. v1.2.3 vs 1.2.3); repository with >100 historical releases pushing the target past the first page; wrong GITHUB_REPOSITORY env value pointing at a fork that lacks the release.","solutions":["Confirm the GitHub Release object exists for the tag (drafts included) in the target repo's Releases page before running the gate.","Check the tag spelling matches a real tag_name exactly, including any leading 'v'.","If the repo has more than 100 releases, paginate the releases endpoint instead of relying on per_page=100, or raise per_page within the documented limit.","Verify GITHUB_REPOSITORY env var points at the repo that owns the release (defaults to stablyai/orca).","Ensure the release-create workflow step has run before this verify step in the publish pipeline."],"exampleFix":"// before\nconst res = await githubFetch(`https://api.github.com/repos/${repo}/releases?per_page=100`, token)\n// after — paginate until the tag is found or releases are exhausted\nasync function fetchRelease(repo, tag, token) {\n  let page = 1\n  while (true) {\n    const res = await githubFetch(`https://api.github.com/repos/${repo}/releases?per_page=100&page=${page}`, token)\n    const releases = await res.json()\n    if (!Array.isArray(releases)) throw new Error(`GitHub releases response for ${repo} was not an array`)\n    const release = releases.find((c) => c.tag_name === tag)\n    if (release) return release\n    if (releases.length < 100) break\n    page += 1\n  }\n  throw new Error(`Release ${repo}@${tag} was not found in the draft-aware releases list`)\n}","handlingStrategy":"validation","validationCode":"// Before calling fetchRelease, confirm the tag format and that a release is expected.\nfunction assertTagShape(tag) {\n  if (!/^v?\\d+\\.\\d+\\.\\d+/.test(tag)) {\n    throw new Error(`Refusing to look up malformed tag: ${tag}`)\n  }\n}\n// In the workflow, ensure the release-create step completed:\n//   if: steps.create_release.outcome == 'success'\n// before invoking verify-release-required-assets.mjs.","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Order the workflow so release creation runs to success before the asset-verify gate.","Echo the tag and GITHUB_REPOSITORY at the start of the step to catch empty/env drift early.","If the repo has >100 releases, paginate the releases endpoint or filter by tag via a pre-check."],"tags":["github-api","release","ci-gate","draft-release"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}