jestjs/jest · error · Error

No exports found in package ${pkg.name}

Error message

No exports found in package ${pkg.name}

What it means

scripts/build.mjs generates an ESM (.mjs) re-export wrapper by requiring the package's CJS entry point (pkg.main) and enumerating its named/default exports. At build.mjs:78-79, if Object.keys(cjsModule) contains nothing other than __esModule/default, the package is considered to export nothing and the build aborts. This catches packages whose entry file has no real public surface before shipping a broken .mjs.

Source

Thrown at scripts/build.mjs:79

      `Main file "${pkg.main}" in "${pkg.name}" should exist`,
    );

    if (typeOnlyPackages.has(pkg.name)) {
      continue;
    }

    // TODO: can we get exports from a file from webpack's `stats`?
    const cjsModule = require(entryPointFile);
    const exportStatements = Object.keys(cjsModule)
      .filter(name => name !== '__esModule' && name !== 'default')
      .map(name => `export const ${name} = cjsModule.${name};`);

    if (cjsModule.default) {
      exportStatements.push('export default cjsModule.default;');
    }

    if (exportStatements.length === 0) {
      throw new Error(`No exports found in package ${pkg.name}`);
    }

    const mjsEntryFile = entryPointFile.replace(/\.js$/, '.mjs');

    const esSource = dedent`
      import cjsModule from './index.js';

      ${exportStatements.join('\n')}
    `;

    await fs.promises.writeFile(mjsEntryFile, `${esSource}\n`);
  }

  process.stdout.write(`${OK}\n`);
}

try {
  await buildNodePackages();

View on GitHub (pinned to f49721c78e)

Solutions

  1. Add at least one named or default export to the package's main entry file (the file referenced by pkg.main).
  2. Confirm pkg.main points at the intended entry file and that file was built (the script first asserts fs.existsSync(entryPointFile)).
  3. Re-run the build after fixing exports; the require() at build.mjs:69 must observe real keys.

Example fix

// before (packages/foo/build/index.js)
function internal() {}
module.exports = {};
// after
function foo() { return 'foo'; }
module.exports = { foo };
Defensive patterns

Strategy: validation

Validate before calling

function assertPackageHasExports(entryFile, pkgName) {
  const mod = require(entryFile);
  const names = Object.keys(mod).filter(k => k !== '__esModule' && k !== 'default');
  if (names.length === 0 && !mod.default) {
    throw new Error(`No exports found in package ${pkgName}`);
  }
}

Type guard

function packageHasExports(entryFile) {
  const mod = require(entryFile);
  const named = Object.keys(mod).filter(k => k !== '__esModule' && k !== 'default');
  return named.length > 0 || !!mod.default;
}

Prevention

When it happens

Trigger: Running the monorepo build (`node scripts/build.mjs` / the build script) for a package whose index.js has no exports — e.g. a barrel file that forgot to re-export, a file with only internal helper declarations, or one where exports are guarded behind a condition that evaluates false at require time.

Common situations: Adding a new package but not yet exporting anything from its entry point; refactoring that moves exports into a sub-module without re-exporting from index.js; side-effectful entry files that assign to a conditional that is falsy during build.

Related errors


AI-assisted analysis of jestjs/jest@f49721c78e (2026-08-03). Data as JSON: /data/errors/d43186dfd73421aa.json. Report an issue: GitHub.