{"record":{"id":"969d4c369ea167c4","repo":"Hmbown/CodeWhale","slug":"invalid-release-tag-tag","errorCode":null,"errorMessage":"Invalid release tag: ${tag}","messagePattern":"Invalid release tag: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/release/ensure-release-assets-absent.js","lineNumber":14,"sourceCode":"#!/usr/bin/env node\n\nconst { execFileSync } = require(\"node:child_process\");\n\nfunction usage() {\n  return \"Usage: node scripts/release/ensure-release-assets-absent.js OWNER/REPO vX.Y.Z\";\n}\n\nfunction validateTarget(repo, tag) {\n  if (!/^[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.-]+$/.test(repo)) {\n    throw new Error(`Invalid GitHub repository: ${repo}`);\n  }\n  if (!/^v[0-9]+\\.[0-9]+\\.[0-9]+$/.test(tag)) {\n    throw new Error(`Invalid release tag: ${tag}`);\n  }\n}\n\nfunction isNotFoundError(error) {\n  return (\n    error &&\n    error.status !== 0 &&\n    /\\bHTTP 404\\b/.test(String(error.stderr || \"\"))\n  );\n}\n\nfunction fetchRelease(repo, tag, ghBin = process.env.GH_BIN || \"gh\", exec = execFileSync) {\n  validateTarget(repo, tag);\n  const endpoint = `repos/${repo}/releases/tags/${encodeURIComponent(tag)}`;\n  let output;\n  try {\n    output = exec(ghBin, [\"api\", endpoint], {\n      encoding: \"utf8\",","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/scripts/release/ensure-release-assets-absent.js#L1-L32","documentation":"validateTarget() rejected the tag argument: it must match ^v[0-9]+\\.[0-9]+\\.[0-9]+$ — a literal 'v' followed by exactly three non-negative integer components. Notably, prerelease and build suffixes are intentionally rejected: '1.2.3' (no v), 'v1.2', 'v1.2.3-rc.1', and 'v1.2.3+build' all fail. The check runs before gh is invoked.","triggerScenarios":"Passing a semver string from package.json (no 'v' prefix); a two-component tag like v1.2; a prerelease tag v1.2.3-rc1; a tag with build metadata v1.2.3+meta.","commonSituations":"Deriving the tag from the package version instead of the pushed git tag; tagging a release candidate and pointing the guard at it; manual invocation typos.","solutions":["Use the exact git tag form vX.Y.Z (e.g. v1.2.3) — in CI take it from github.ref_name or the pushed tag","For prereleases, either retag as a stable vX.Y.Z or deliberately widen the regex if your process supports pre-release asset guards","When converting from a semver string, prefix with 'v' and strip any prerelease/build suffix"],"exampleFix":"# before\nnode scripts/release/ensure-release-assets-absent.js acme/codewhale 1.2.3\n\n# after\nnode scripts/release/ensure-release-assets-absent.js acme/codewhale v1.2.3","handlingStrategy":"validation","validationCode":"function isValidReleaseTag(tag) {\n  return /^v[0-9]+\\.[0-9]+\\.[0-9]+$/.test(tag);\n}\n// before invoking:\nif (!isValidReleaseTag(tag)) throw new Error(`pass vX.Y.Z exactly (got ${tag}); prerelease suffixes are rejected`);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Take the tag from github.ref_name on tag push events rather than deriving it from package.json","Remember the guard is strict: no '1.2.3', no 'v1.2', no '-rc.1' / '+build' suffixes","If prerelease tags must be supported, widen the regex deliberately in a reviewed change"],"tags":["cli","validation","release","versioning"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}