Hmbown/CodeWhale · error · Error
Downloaded release artifacts are missing ${name} at ${source
Error message
Downloaded release artifacts are missing ${name} at ${source} What it means
During assemble(), an expected release asset was not found at its computed intermediate path: bundle assets and BUNDLE_CHECKSUM_MANIFEST live at INPUT_DIR/codewhale-bundles/<name>, everything else at INPUT_DIR/<name>/<name>. The ENOENT is converted into this named error with the exact path, meaning the CI artifact-download step did not deliver every expected file.
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 8880682c63)
Solutions
- Check the path in the message and place the file at INPUT_DIR/<name>/<name> (or INPUT_DIR/codewhale-bundles/<name> for bundles)
- Re-run the full build workflow so every artifact is uploaded, then re-download all artifacts into INPUT_DIR before assemble
- Verify the upload workflow's artifact names still cover allReleaseAssetNames()
- Pass the directory that directly contains the per-artifact subfolders — not the workspace root
Example fix
# before: missing INPUT_DIR/codewhale-aarch64-linux/codewhale-aarch64-linux.tar.gz # after: re-download every workflow artifact into a clean input dir rm -rf artifacts-in && mkdir artifacts-in gh run download <run-id> -D artifacts-in node scripts/release/assemble-release-assets.js artifacts-in release-out
Defensive patterns
Strategy: validation
Validate before calling
const fs = require("node:fs/promises");
const path = require("node:path");
const {
allReleaseAssetNames,
BUNDLE_ASSET_NAMES,
BUNDLE_CHECKSUM_MANIFEST,
CHECKSUM_MANIFEST,
} = require("./npm/codewhale/scripts/artifacts");
function intermediateArtifactPath(inputDir, name) {
return name === BUNDLE_CHECKSUM_MANIFEST || BUNDLE_ASSET_NAMES.includes(name)
? path.join(inputDir, "codewhale-bundles", name)
: path.join(inputDir, name, name);
}
async function assertArtifactsPresent(inputDir) {
const missing = [];
for (const name of allReleaseAssetNames()) {
if (name === "codewhale.bat" || name === CHECKSUM_MANIFEST) continue; // generated at assemble time
try {
await fs.access(intermediateArtifactPath(inputDir, name));
} catch {
missing.push(intermediateArtifactPath(inputDir, name));
}
}
if (missing.length > 0) throw new Error(`input directory is missing: ${missing.join(", ")}`);
} Prevention
- Fail the workflow when any artifact upload step is skipped, so downloads can never be partial
- Download all artifacts into a dedicated clean directory with actions/download-artifact (no name filter) or gh run download
- Keep workflow artifact names in lockstep with allReleaseAssetNames(); review both together in the same PR
- Remember the layout: INPUT_DIR/<name>/<name> for binaries, INPUT_DIR/codewhale-bundles/<name> for bundles
When it happens
Trigger: Running assemble with an INPUT_DIR lacking e.g. INPUT_DIR/codewhale-windows-x64.exe/codewhale-windows-x64.exe or INPUT_DIR/codewhale-bundles/<bundle>.tar.gz; an upload step that failed silently; artifact names renamed in the workflow; passing the wrong directory (repo root or workspace) as INPUT_DIR.
Common situations: actions/download-artifact fetching only some artifacts because an upload step was skipped on a matrix leg; artifact name drift after workflow edits; downloading to a nested path and passing its parent.
Related errors
- ${label} does not match the authoritative inventory; missing
- Release asset directory must be flat; found: ${nonFiles.map(
- Downloaded release artifact must be a regular file: ${source
- Output directory must be empty: ${outputDirectory}
- CODEWHALE_SMOKE_ASSETS_DIR is not a directory: ${releaseAsse
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/dd69d46ddf7783a9.
Report an issue: GitHub.