{"record":{"id":"12638ed3a004d1f9","repo":"chenglou/pretext","slug":"expected-exactly-one-tarball-in-packdir-found","errorCode":null,"errorMessage":"Expected exactly one tarball in ${packDir}, found ${tarballs.length}","messagePattern":"Expected exactly one tarball in (.+?), found (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/package-smoke-test.ts","lineNumber":38,"sourceCode":"  if (!keepTemp && succeeded) {\n    await rm(tempRoot, { recursive: true, force: true })\n  }\n}\n\nasync function packPackage(): Promise<string> {\n  const packDir = path.join(tempRoot, 'pack')\n  await mkdir(packDir, { recursive: true })\n\n  run(['npm', 'pack', '--pack-destination', packDir], {\n    cwd: root,\n    stdout: 'inherit',\n    stderr: 'inherit',\n  })\n\n  const entries = await readdir(packDir)\n  const tarballs = entries.filter(entry => entry.endsWith('.tgz'))\n  if (tarballs.length !== 1) {\n    throw new Error(`Expected exactly one tarball in ${packDir}, found ${tarballs.length}`)\n  }\n  return path.join(packDir, tarballs[0]!)\n}\n\nasync function smokeJavaScriptEsm(tarballPath: string): Promise<void> {\n  const projectDir = path.join(tempRoot, 'js-esm')\n  await createProject(projectDir, {\n    name: 'pretext-package-smoke-js-esm',\n    private: true,\n    type: 'module',\n  })\n\n  await installTarball(projectDir, tarballPath)\n  await writeFile(\n    path.join(projectDir, 'index.js'),\n    [\n      \"import * as pretext from '@chenglou/pretext'\",\n      \"if (typeof pretext.prepare !== 'function') throw new Error('prepare export missing')\",","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/chenglou/pretext/blob/ac49b09b7d83ede19581fa94a8b892b07d309baf/scripts/package-smoke-test.ts#L20-L56","documentation":"packPackage() in package-smoke-test.ts runs `npm pack` into a temp directory, then asserts that exactly one `.tgz` was produced. It throws on zero or more than one. This protects the smoke test's assumption that the published artifact is a single tarball it can install.","triggerScenarios":"Zero tarballs: `npm pack` wrote nothing (e.g. package not buildable, dist/ missing on a clean checkout). More than one: package.json defines multiple packages or a prior pack left stale `.tgz` files in the pack dir (shouldn't happen since packDir is freshly made, but a misconfigured `files`/`prepack` could).","commonSituations":"Running the smoke test without building dist/ first (the published entrypoints target dist/layout.js), or running it in a worktree with an unusual package layout.","solutions":["Ensure `dist/` is built before packing (run the build step that emits dist/layout.js + dist/layout.d.ts).","Run `npm pack` manually and inspect what it produces: `npm pack --dry-run` to see the file list.","Confirm package.json has a single name and no nested package manifests that could cause double packing.","Check the temp pack dir printed in the error for leftover `.tgz` artifacts."],"exampleFix":"# before — dist not built, npm pack emits nothing\nbun run package-smoke-test\n\n# after\nbun run build   # or whichever step emits dist/\nbun run package-smoke-test","handlingStrategy":"validation","validationCode":"import { readdir } from 'node:fs/promises'\n\nasync function expectSingleTarball(packDir: string): Promise<string> {\n  const tarballs = (await readdir(packDir)).filter(e => e.endsWith('.tgz'))\n  if (tarballs.length !== 1) {\n    console.error(`Expected 1 tarball, found ${tarballs.length}. Run \\`npm pack --dry-run\\` to inspect.`)\n    process.exit(1)\n  }\n  return tarballs[0]!\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Build dist/ before running the smoke test (published entrypoints target dist/layout.js).","Run `npm pack --dry-run` first to confirm the file list and that exactly one tarball is produced."],"tags":["packaging","npm","smoke-test"],"backgroundTag":null,"analyzedSha":"ac49b09b7d83ede19581fa94a8b892b07d309baf","analyzedAt":"2026-08-12T17:03:16.263Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}