{"record":{"id":"dd69d46ddf7783a9","repo":"Hmbown/CodeWhale","slug":"downloaded-release-artifacts-are-missing-name-a","errorCode":null,"errorMessage":"Downloaded release artifacts are missing ${name} at ${source}","messagePattern":"Downloaded release artifacts are missing (.+?) at (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/release/assemble-release-assets.js","lineNumber":130,"sourceCode":"  if (name === BUNDLE_CHECKSUM_MANIFEST || BUNDLE_ASSET_NAMES.includes(name)) {\n    return path.join(inputDirectory, \"codewhale-bundles\", name);\n  }\n  return path.join(inputDirectory, name, name);\n}\n\nasync function assemble(inputDirectory, outputDirectory) {\n  const expected = allReleaseAssetNames();\n  const generated = new Set([WINDOWS_LAUNCHER, CHECKSUM_MANIFEST]);\n  const copiedNames = expected.filter((name) => !generated.has(name));\n  const sources = new Map();\n  for (const name of copiedNames) {\n    const source = intermediateArtifactPath(inputDirectory, name);\n    let sourceStat;\n    try {\n      sourceStat = await fs.lstat(source);\n    } catch (error) {\n      if (error && error.code === \"ENOENT\") {\n        throw new Error(`Downloaded release artifacts are missing ${name} at ${source}`);\n      }\n      throw error;\n    }\n    if (!sourceStat.isFile()) {\n      throw new Error(`Downloaded release artifact must be a regular file: ${source}`);\n    }\n    sources.set(name, source);\n  }\n\n  await fs.mkdir(outputDirectory, { recursive: true });\n  const existing = await fs.readdir(outputDirectory);\n  if (existing.length > 0) {\n    throw new Error(`Output directory must be empty: ${outputDirectory}`);\n  }\n\n  for (const name of copiedNames) {\n    await fs.copyFile(sources.get(name), path.join(outputDirectory, name));\n  }","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/scripts/release/assemble-release-assets.js#L112-L148","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before: missing INPUT_DIR/codewhale-aarch64-linux/codewhale-aarch64-linux.tar.gz\n\n# after: re-download every workflow artifact into a clean input dir\nrm -rf artifacts-in && mkdir artifacts-in\ngh run download <run-id> -D artifacts-in\nnode scripts/release/assemble-release-assets.js artifacts-in release-out","handlingStrategy":"validation","validationCode":"const fs = require(\"node:fs/promises\");\nconst path = require(\"node:path\");\nconst {\n  allReleaseAssetNames,\n  BUNDLE_ASSET_NAMES,\n  BUNDLE_CHECKSUM_MANIFEST,\n  CHECKSUM_MANIFEST,\n} = require(\"./npm/codewhale/scripts/artifacts\");\nfunction intermediateArtifactPath(inputDir, name) {\n  return name === BUNDLE_CHECKSUM_MANIFEST || BUNDLE_ASSET_NAMES.includes(name)\n    ? path.join(inputDir, \"codewhale-bundles\", name)\n    : path.join(inputDir, name, name);\n}\nasync function assertArtifactsPresent(inputDir) {\n  const missing = [];\n  for (const name of allReleaseAssetNames()) {\n    if (name === \"codewhale.bat\" || name === CHECKSUM_MANIFEST) continue; // generated at assemble time\n    try {\n      await fs.access(intermediateArtifactPath(inputDir, name));\n    } catch {\n      missing.push(intermediateArtifactPath(inputDir, name));\n    }\n  }\n  if (missing.length > 0) throw new Error(`input directory is missing: ${missing.join(\", \")}`);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["release","ci","artifacts","filesystem","validation"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}