{"record":{"id":"42ded6490fe50016","repo":"Hmbown/CodeWhale","slug":"annotated-tag-tag-did-not-peel-to-a-commit-sha","errorCode":null,"errorMessage":"Annotated tag ${tag} did not peel to a commit SHA","messagePattern":"Annotated tag (.+?) did not peel to a commit SHA","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"npm/codewhale/scripts/verify-release-assets.js","lineNumber":212,"sourceCode":"\nasync function githubApi(repo, path) {\n  return downloadJson(githubApiUrl(repo, path));\n}\n\nasync function resolveTagCommitSha(repo, tag) {\n  const ref = await githubApi(repo, `/git/ref/tags/${encodeURIComponent(tag)}`);\n  if (!ref.object || !ref.object.sha || !ref.object.type) {\n    throw new Error(`GitHub tag ref ${tag} did not include an object SHA`);\n  }\n  if (ref.object.type === \"commit\") {\n    return ref.object.sha;\n  }\n  if (ref.object.type !== \"tag\") {\n    throw new Error(`GitHub tag ref ${tag} points at ${ref.object.type}, not a commit or annotated tag`);\n  }\n  const tagObject = await githubApi(repo, `/git/tags/${ref.object.sha}`);\n  if (!tagObject.object || tagObject.object.type !== \"commit\" || !tagObject.object.sha) {\n    throw new Error(`Annotated tag ${tag} did not peel to a commit SHA`);\n  }\n  return tagObject.object.sha;\n}\n\nasync function findReleaseWorkflowRun(repo, tag, tagSha, api = githubApi) {\n  const runs = await api(repo, \"/actions/workflows/release.yml/runs?per_page=100\");\n  const candidates = (runs.workflow_runs || [])\n    .filter((run) => run.head_sha === tagSha)\n    .filter((run) => run.event === \"push\" || run.event === \"workflow_dispatch\")\n    .sort((a, b) => String(b.updated_at).localeCompare(String(a.updated_at)));\n\n  const orderedCandidates = [\n    ...candidates.filter((run) => run.head_branch === tag),\n    ...candidates.filter((run) => run.head_branch !== tag),\n  ];\n  for (const candidate of orderedCandidates) {\n    const runId = candidate.database_id || candidate.id;\n    if (!runId) {","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/npm/codewhale/scripts/verify-release-assets.js#L194-L230","documentation":"resolveTagCommitSha verifies a GitHub tag ref points at a commit. If the ref points at an annotated tag object, the script fetches the tag object via /git/tags/<sha> and expects it to peel to a commit. This error means the annotated tag object's inner object is missing, not of type 'commit', or lacks a sha, so the tag cannot be resolved to a commit.","triggerScenarios":"A GitHub tag ref resolves to an annotated tag whose /git/tags payload has object.type != 'commit' (e.g. the tag points at a tree or blob), has no nested object, or no sha — typically a malformed or hand-crafted tag object.","commonSituations":"Re-tagging a release manually with a malformed annotated tag; a CI step creating tags with wrong target; API drift where the tag object references another tag or non-commit object.","solutions":["Inspect the tag with `gh api repos/<repo>/git/tags/<sha>` and confirm object.type is 'commit'.","Recreate the tag on the intended commit: `git tag -f -a <tag> <commit> && git push -f origin <tag>`.","If the tag points at another tag, peel one level or re-tag directly against the commit."],"exampleFix":"// before: tag created against wrong target\ngit tag -a v1.0.0 refs/heads/other\n// after\ngit tag -f -a v1.0.0 <commit-sha> && git push -f origin v1.0.0","handlingStrategy":"validation","validationCode":"const ref = await githubApi(repo, `/git/tags/...`); if (ref.object?.type !== \"commit\") throw new Error(\"tag must peel to a commit before verify\");","typeGuard":"function peelsToCommit(tagObject) { return !!tagObject?.object && tagObject.object.type === \"commit\" && typeof tagObject.object.sha === \"string\" && tagObject.object.sha.length > 0; }","tryCatchPattern":"try { const sha = await resolveTagCommitSha(repo, tag); } catch (e) { if (e.message.includes(\"did not peel\")) { console.error(`Re-tag ${tag} against a commit`); process.exit(1); } throw e; }","preventionTips":["Always create release tags with `git tag -a <tag> <commit>`","Verify tags with `gh api repos/<repo>/git/refs/tags/<tag>` before publishing","Never point annotated tags at other tags or non-commit objects"],"tags":["git","github-api","release","tagging"],"backgroundTag":"unexpected-response-shape","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-22T16:17:23.217Z"}