{"record":{"id":"05bda1c100c63dec","repo":"Hmbown/CodeWhale","slug":"github-tag-ref-tag-did-not-include-an-object-sha","errorCode":null,"errorMessage":"GitHub tag ref ${tag} did not include an object SHA","messagePattern":"GitHub tag ref (.+?) did not include an object SHA","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"npm/codewhale/scripts/verify-release-assets.js","lineNumber":202,"sourceCode":"          resolve(parsed);\n        });\n      })\n      .on(\"error\", reject);\n  });\n}\n\nfunction githubApiUrl(repo, path) {\n  return `https://api.github.com/repos/${repo}${path}`;\n}\n\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)","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/npm/codewhale/scripts/verify-release-assets.js#L184-L220","documentation":"resolveTagCommitSha fetches /git/ref/tags/<tag> from the GitHub API and expects an object with object.sha and object.type. If the API response lacks these fields, the tag ref could not be resolved and the script aborts.","triggerScenarios":"tagSha() calls resolveTagCommitSha for a release tag and the API returns a body without object.sha/type — e.g. tag does not exist (empty/error body), truncated response, or non-GitHub API response from a proxy.","commonSituations":"Verifying a release whose git tag was pushed but not yet visible via API; typo in tag name; proxy returning an HTML error page instead of JSON with 200.","solutions":["Verify the tag exists: git ls-remote --tags origin <tag> or check GitHub releases page","Correct the tag name/version passed to the verification script","Ensure the API endpoint is the real GitHub API and GITHUB_TOKEN is valid","Re-push the tag if it was deleted"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const res = await fetch(`https://api.github.com/repos/${repo}/git/ref/tags/${tag}`, { headers: ghHeaders });\nconst ref = await res.json();\nif (!ref || !ref.object || !ref.object.sha || !ref.object.type) {\n  throw new Error(`Tag ${tag} not resolvable via GitHub API (HTTP ${res.status}); check tag exists and token is valid`);\n}","typeGuard":null,"tryCatchPattern":"try { sha = await tagSha(repo, tag); } catch (e) { if (/did not include an object SHA/.test(e.message)) { console.error(`Tag ${tag} missing or API response invalid; verify with gh api`); throw e; } throw e; }","preventionTips":["Verify tags exist with git ls-remote before verification","Ensure valid GITHUB_TOKEN to avoid error bodies misread as success","Reject non-JSON API responses early"],"tags":["github-api","git","release","validation"],"backgroundTag":"unexpected-api-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"}