{"record":{"id":"1ddcac4a94dd42cc","repo":"tinyhumansai/openhuman","slug":"could-not-resolve-latest-github-release-tag-for","errorCode":null,"errorMessage":"Could not resolve latest GitHub Release tag for ${repo}","messagePattern":"Could not resolve latest GitHub Release tag for (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/release/generate-release-notes.mjs","lineNumber":152,"sourceCode":"  if (to !== 'latest-tag') {\n    return to;\n  }\n\n  const tag = runGit(['describe', '--tags', '--abbrev=0']);\n  if (!tag) {\n    throw new Error('Could not resolve latest tag');\n  }\n  return tag;\n}\n\nfunction resolveStartRef(repo, from) {\n  if (from !== 'latest-release') {\n    return from;\n  }\n\n  const tag = runGh(['release', 'view', '--repo', repo, '--json', 'tagName', '--jq', '.tagName']);\n  if (!tag) {\n    throw new Error(`Could not resolve latest GitHub Release tag for ${repo}`);\n  }\n  return tag;\n}\n\nfunction assertRefExists(ref, label) {\n  try {\n    runGit(['rev-parse', '--verify', `${ref}^{commit}`], { allowFailure: true });\n  } catch {\n    throw new Error(`${label} ref not found: ${ref}`);\n  }\n}\n\nexport function extractPullRequestNumbers(subject) {\n  const matches = [...String(subject || '').matchAll(/\\(#(\\d+)\\)/g)];\n  return [...new Set(matches.map((match) => Number(match[1])).filter(Number.isInteger))];\n}\n\nexport function parseGitLog(logText) {","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/scripts/release/generate-release-notes.mjs#L134-L170","documentation":"Thrown by resolveStartRef() when --from latest-release (the default) is used: it runs `gh release view --repo <repo> --json tagName --jq .tagName` to find the previous release tag that bounds the commit range. runGh uses execFileSync, so a hard gh failure (no releases at all) throws its own exec error with gh's stderr; this specific error fires when gh exits 0 but the resolved tag string is empty, leaving the script without a start ref.","triggerScenarios":"Running generate-release-notes.mjs with --from latest-release where the latest GitHub Release has no tagName resolvable by the jq filter, or where gh succeeds but prints empty output (edge states like a release whose tag object is missing). The practical neighborhood: first-ever release cut on a repo (no Release object), only-draft releases (gh release view then fails non-zero, producing the execFileSync error instead), or --repo/GITHUB_REPOSITORY pointing at a repo whose releases are not visible to the authenticated gh.","commonSituations":"Cutting the first release of a new repository; GITHUB_REPOSITORY env leaking a different slug in CI; gh authenticated to an org without release read scope; transferred/renamed repos where the old slug still resolves but shows no releases.","solutions":["Pass an explicit start ref instead: --from <previous-tag> (e.g. --from v0.57.18) — this is also what the script's own usage examples do for first cuts","Check what gh actually returns: gh release view --repo <owner/repo> --json tagName --jq .tagName — an error or empty output reproduces the script's view","Verify repo resolution: the script prefers --repo then GITHUB_REPOSITORY then the upstream/origin remotes; make sure they agree","If the latest release is still a draft, publish it (gh release edit <tag> --draft=false) so latest-release can resolve it"],"exampleFix":"# before\nnode scripts/release/generate-release-notes.mjs --from latest-release   # first release, nothing to resolve\n\n# after — pin the start ref explicitly\nnode scripts/release/generate-release-notes.mjs --from v0.57.18 --to main","handlingStrategy":"validation","validationCode":"# preflight before invoking the script\ntag=$(gh release view --repo \"$REPO\" --json tagName --jq '.tagName' 2>/dev/null)\nif [ -z \"$tag\" ]; then\n  echo \"no published release on $REPO — pass --from <ref> explicitly\" >&2\n  exit 1\nfi\nnode scripts/release/generate-release-notes.mjs --repo \"$REPO\" --from latest-release","typeGuard":null,"tryCatchPattern":"if ! node scripts/release/generate-release-notes.mjs --from latest-release; then\n  echo 'latest-release unresolvable; retrying with pinned tag' >&2\n  node scripts/release/generate-release-notes.mjs --from \"${LAST_KNOWN_TAG:?set LAST_KNOWN_TAG}\"\nfi","preventionTips":["publish the release before relying on --from latest-release","pin --from to an explicit tag in CI for reproducible ranges","add a gh release view preflight step to the release workflow"],"tags":["github-cli","release-notes","release-automation","configuration"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}