Hmbown/CodeWhale · error · Error

GitHub Release is missing required release asset(s)

Error message

GitHub Release is missing required release asset(s): ${missing.join(", ")}

What it means

assertReleaseAssetsFresh first checks that every expected asset name is present on the GitHub Release; if any are absent it throws listing the missing names. The verifier treats an incomplete release as unsafe to publish against.

Solutions

  1. Compare the release's asset list against the expected names; re-run the Release workflow to re-upload missing assets.
  2. Confirm resolveBinaryVersion() matches the version the release was built for.
  3. Check the release workflow's upload steps for silent failures or renamed artifacts.

Example fix

// workflow: re-upload missing assets
gh release upload v1.2.3 dist/codewhale-linux-x64.tar.gz --clobber
Defensive patterns

Strategy: validation

Validate before calling

const names = new Set((release.assets ?? []).map(a => a.name)); const missing = expectedAssets.filter(a => !names.has(a)); if (missing.length) console.error("Missing assets:", missing);

Type guard

null

Try / catch

try { await verifyGitHubReleaseFreshness(repo, version, expected); } catch (e) { if (e.message.includes("missing required release asset")) { console.error("Re-run the Release workflow to upload all assets."); process.exit(1); } throw e; }

Prevention

When it happens

Trigger: verifyGitHubReleaseFreshness is called and the Release's assets array lacks one or more of the expected asset names (checked via assetsByName.has).

Common situations: Release workflow partially failed so some platform binaries were never uploaded; assets manually deleted from the release; version mismatch between npm and the GitHub release (expected names differ).

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/288787cfc815d2e7. Report an issue: GitHub.

Appendix: source

Thrown at npm/codewhale/scripts/verify-release-assets.js:270

  throw new Error(
    `No successful asset-publishing job found in release.yml workflow runs for ${tag} at ${tagSha}. ` +
      "Repair the Release workflow before publishing npm.",
  );
}

function parseGitHubTime(value, label) {
  const timestamp = Date.parse(value);
  if (!Number.isFinite(timestamp)) {
    throw new Error(`GitHub ${label} timestamp is invalid: ${value}`);
  }
  return timestamp;
}

function assertReleaseAssetsFresh(release, expectedAssets, run) {
  const assetsByName = new Map((release.assets || []).map((asset) => [asset.name, asset]));
  const missing = expectedAssets.filter((asset) => !assetsByName.has(asset));
  if (missing.length > 0) {
    throw new Error(`GitHub Release is missing required release asset(s): ${missing.join(", ")}`);
  }

  // #5429: compare against the successful release job's started_at when the
  // run record carries it; fall back to the run-level timestamp only when a
  // job baseline is unavailable.
  const baseline = run.release_job_started_at || run.run_started_at || run.created_at;
  const baselineLabel = run.release_job_started_at ? "release job start" : "workflow run start";
  const freshnessBaseline = parseGitHubTime(baseline, baselineLabel);
  const stale = [];
  for (const expected of expectedAssets) {
    const asset = assetsByName.get(expected);
    if (asset.state && asset.state !== "uploaded") {
      stale.push(`${expected} has state ${asset.state}`);
      continue;
    }
    const updatedAt = parseGitHubTime(asset.updated_at || asset.created_at, `${expected} update`);
    if (updatedAt < freshnessBaseline) {
      stale.push(`${expected} updated at ${asset.updated_at || asset.created_at}`);

View on GitHub (pinned to 433685b202)