Hmbown/CodeWhale · error · Error
Downloaded release artifacts are missing
Error message
Downloaded release artifacts are missing ${name} at ${source} What it means
assemble walks the expected release asset names and lstat()s each intermediate artifact at its expected source path. When lstat fails with ENOENT (the file does not exist), it rethrows this Error identifying which asset is missing and where it was expected, instead of surfacing the raw ENOENT.
Solutions
- Re-run the artifact download step so every expected asset lands in the input directory.
- Check the input directory path passed to assemble is the one the downloader wrote to.
- Verify the asset name in the message against what the build actually produced; align names if the upstream artifact was renamed.
Example fix
// before node assemble-release-assets.js --input ./empty-dir ... // after node assemble-release-assets.js --input ./downloaded-assets # contains all expected assets
Defensive patterns
Strategy: validation
Validate before calling
for (const name of allReleaseAssetNames()) {
try { await fs.access(path.join(inputDir, name)); }
catch { throw new Error(`missing ${name} in ${inputDir}`); }
} Try / catch
try { await assemble(...); } catch (e) { if (String(e.message).startsWith('Downloaded release artifacts are missing')) { console.error('Re-run the download step:', e.message); process.exitCode = 1; } else throw e; } Prevention
- Verify the download step completed (count files) before assembling.
- Fail the download job loudly on partial completion.
- Keep the input directory path in one shared config for download and assemble.
When it happens
Trigger: Calling assemble with an inputDirectory that does not contain one of the expected asset files, e.g. an incomplete download set or a wrong --input path.
Common situations: A CI download step failed or partially completed, the artifact was renamed upstream, or the input directory path is misconfigured in the release job.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- No release.yml workflow run found for
- No successful asset-publishing job found in release.yml…
- npm package version does not match codewhaleBinaryVersion …
- A full Git history is required to establish the PR merge…
- account_agent_model_unconfigured
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/dd69d46ddf7783a9.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/release/assemble-release-assets.js:130
if (name === BUNDLE_CHECKSUM_MANIFEST || BUNDLE_ASSET_NAMES.includes(name)) {
return path.join(inputDirectory, "codewhale-bundles", name);
}
return path.join(inputDirectory, name, name);
}
async function assemble(inputDirectory, outputDirectory) {
const expected = allReleaseAssetNames();
const generated = new Set([WINDOWS_LAUNCHER, CHECKSUM_MANIFEST]);
const copiedNames = expected.filter((name) => !generated.has(name));
const sources = new Map();
for (const name of copiedNames) {
const source = intermediateArtifactPath(inputDirectory, name);
let sourceStat;
try {
sourceStat = await fs.lstat(source);
} catch (error) {
if (error && error.code === "ENOENT") {
throw new Error(`Downloaded release artifacts are missing ${name} at ${source}`);
}
throw error;
}
if (!sourceStat.isFile()) {
throw new Error(`Downloaded release artifact must be a regular file: ${source}`);
}
sources.set(name, source);
}
await fs.mkdir(outputDirectory, { recursive: true });
const existing = await fs.readdir(outputDirectory);
if (existing.length > 0) {
throw new Error(`Output directory must be empty: ${outputDirectory}`);
}
for (const name of copiedNames) {
await fs.copyFile(sources.get(name), path.join(outputDirectory, name));
}View on GitHub (pinned to 433685b202)