{"record":{"id":"c6fa05c49cb57972","repo":"windmill-labs/windmill","slug":"esbuild-wasm-version-tarball-did-not-contain-li","errorCode":null,"errorMessage":"esbuild-wasm@${version} tarball did not contain lib/main.js","messagePattern":"esbuild-wasm@(.+?) tarball did not contain lib/main\\.js","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/src/utils/esbuild_loader.ts","lineNumber":143,"sourceCode":"  log.info(`Downloading esbuild-wasm@${version} from ${url} ...`);\n  const res = await fetch(url);\n  if (!res.ok || !res.body) {\n    throw new Error(\n      `Failed to download esbuild-wasm@${version} (${res.status} ${res.statusText}). ` +\n        `Set WINDMILL_ESBUILD_WASM_PATH to an extracted esbuild-wasm package dir, ` +\n        `point WINDMILL_ESBUILD_WASM_URL at a reachable tarball, or repair the native esbuild install.`\n    );\n  }\n\n  // Extract to a unique temp dir and rename into place so a crash or a\n  // concurrent writer can't leave a half-extracted package behind, and so two\n  // extractions never share an in-progress directory.\n  const tmpDir = `${destDir}.${process.pid}.${extractCounter++}.tmp`;\n  fs.rmSync(tmpDir, { recursive: true, force: true });\n  await extractTarball(res.body, tmpDir);\n  if (!fs.existsSync(path.join(tmpDir, \"lib\", \"main.js\"))) {\n    fs.rmSync(tmpDir, { recursive: true, force: true });\n    throw new Error(`esbuild-wasm@${version} tarball did not contain lib/main.js`);\n  }\n  try {\n    fs.renameSync(tmpDir, destDir);\n  } catch {\n    // Another process won the race, or rename across devices failed; clean up\n    // and let the existsSync check below decide whether the cache is usable.\n    fs.rmSync(tmpDir, { recursive: true, force: true });\n  }\n  if (!fs.existsSync(path.join(destDir, \"lib\", \"main.js\"))) {\n    throw new Error(`Failed to cache esbuild-wasm@${version} at ${destDir}`);\n  }\n  return destDir;\n}\n\n/**\n * Resolves a tar entry to an absolute path inside destDir, stripping the leading\n * \"package/\" component that npm tarballs use. Returns null if the entry would\n * escape destDir (tar-slip), since WINDMILL_ESBUILD_WASM_URL allows untrusted","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/cli/src/utils/esbuild_loader.ts#L125-L161","documentation":"Thrown by ensureWasmPackage after extracting the esbuild-wasm tarball: the extracted contents did not include lib/main.js, so the extracted package cannot be loaded as the esbuild JS host. The loader deletes the temp dir and refuses to cache the incomplete package. It guards against pointing WINDMILL_ESBUILD_WASM_URL at something that is not a valid esbuild-wasm npm-style tarball.","triggerScenarios":"The tarball downloaded from WINDMILL_ESBUILD_WASM_URL (or a proxy-intercepted response) extracted successfully but has no lib/main.js at its root after stripping the leading package/ component — i.e. it is not an esbuild-wasm package tarball, is a wrong/truncated artifact, or has an unexpected inner layout.","commonSituations":"WINDMILL_ESBUILD_WASM_URL pointing at a GitHub archive, a wrong package's tarball, or an HTML error page saved as .tgz; an internal mirror serving an older tarball layout; a corrupted upload in a self-hosted mirror; a manually crafted tarball missing the package/ prefix the extractor strips.","solutions":["Point WINDMILL_ESBUILD_WASM_URL at the official npm tarball layout, e.g. https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-<version>.tgz.","Verify the artifact: `tar tzf file.tgz | grep lib/main.js` must list package/lib/main.js.","Set WINDMILL_ESBUILD_WASM_PATH to a correctly extracted esbuild-wasm package directory instead of relying on a URL.","Re-upload/fix the artifact in your internal mirror if it is truncated or the wrong package."],"exampleFix":"// before\nWINDMILL_ESBUILD_WASM_URL=https://github.com/evanw/esbuild/archive/refs/tags/v0.28.0.tar.gz\n// after: use the npm-style package tarball\nWINDMILL_ESBUILD_WASM_URL=https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.28.0.tgz","handlingStrategy":"validation","validationCode":"import { execSync } from \"node:child_process\";\nconst url = process.env.WINDMILL_ESBUILD_WASM_URL;\nif (url) {\n  const out = execSync(`tar tzf <(curl -fsSL ${url}) 2>/dev/null || curl -fsSL ${url} | tar tz`, { shell: \"/bin/bash\" }).toString();\n  if (!out.split(\"\\n\").some((n) => /(^|\\/)lib\\/main\\.js$/.test(n.replace(/^package\\//, \"\")))) {\n    throw new Error(`Tarball at ${url} has no lib/main.js — use an esbuild-wasm npm package tarball`);\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await getEsbuild();\n} catch (e) {\n  if (String(e).includes(\"did not contain lib/main.js\")) {\n    console.error(\"WINDMILL_ESBUILD_WASM_URL must point at an esbuild-wasm npm tarball (package/lib/main.js inside)\");\n  }\n  throw e;\n}","preventionTips":["Only point WINDMILL_ESBUILD_WASM_URL at npm-registry-style esbuild-wasm tarballs, not GitHub source archives.","Validate mirrors with `tar tzf` and grep for package/lib/main.js before deploying.","Pin the exact esbuild-wasm version tarball matching the CLI's esbuild pin.","Prefer WINDMILL_ESBUILD_WASM_PATH with a manually extracted, verified package in air-gapped setups."],"tags":["tarball","esbuild","artifact-corrupt","config"],"backgroundTag":"invalid-package-tarball","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}