vitest-dev/vitest · error · Error

Cannot parse the module format of '${url}' because "module.f

Error message

Cannot parse the module format of '${url}' because "module.findPackageJSON" is not available. Upgrade to Node 22.14 to use this feature. This is NOT a bug of Vitest.

What it means

To classify a `.js`/`.ts`/extensionless file as ESM or CJS, the mocker reads the nearest `package.json` `"type"` field through Node's `module.findPackageJSON` (added in Node 22.14). When that function is missing, the module format cannot be determined safely, so `resolveModuleFormat` throws instead of guessing wrong and producing an invalid mock.

Source

Thrown at packages/mocker/src/node/parsers.ts:138

    return []
  }

  return Array.from(new Set(exports))
}

export function resolveModuleFormat(url: string, code: string): 'module' | 'commonjs' | undefined {
  const ext = extname(url)

  if (ext === '.cjs' || ext === '.cts') {
    return 'commonjs'
  }
  else if (ext === '.mjs' || ext === '.mts') {
    return 'module'
  }
  // https://nodejs.org/api/packages.html#syntax-detection
  else if (ext === '.js' || ext === '.ts' || ext === '') {
    if (!module.findPackageJSON) {
      throw new Error(`Cannot parse the module format of '${url}' because "module.findPackageJSON" is not available. Upgrade to Node 22.14 to use this feature. This is NOT a bug of Vitest.`)
    }
    const pkgJsonPath = module.findPackageJSON(url)
    const pkgJson = pkgJsonPath ? JSON.parse(readFileSync(pkgJsonPath, 'utf-8')) : {}
    if (pkgJson?.type === 'module') {
      return 'module'
    }
    else if (pkgJson?.type === 'commonjs') {
      return 'commonjs'
    }
    else {
      // Ambiguous input! Check if it has ESM syntax. Node.js is much smarter here,
      // but we don't need to run the code, so we can be more relaxed
      if (hasESM(filterOutComments(code))) {
        return 'module'
      }
      else {
        return 'commonjs'
      }

View on GitHub (pinned to d568f8ce37)

Solutions

  1. Upgrade Node.js to 22.14 or newer.
  2. Give the target an explicit extension: rename to `.mjs` or `.cjs` so `resolveModuleFormat` short-circuits before needing `findPackageJSON`.
  3. Provide an explicit factory via `vi.mock(specifier, () => ({ ... }))` to bypass format detection.

Example fix

// before (ambiguous .js, Node < 22.14)
vi.mock('./legacy.js')

// after: explicit extension avoids package.json lookup
vi.mock('./legacy.cjs')
Defensive patterns

Strategy: validation

Validate before calling

import module from 'node:module'

const canFindPkg = typeof module.findPackageJSON === 'function'
if (!canFindPkg) {
  console.warn(
    `vi.mock format detection needs Node >= 22.14 (module.findPackageJSON); current is ${process.version}.`,
  )
}

Prevention

When it happens

Trigger: Mocking a `.js` dependency whose ESM/CJS nature must be resolved from `package.json`, on Node older than 22.14, hitting the `!module.findPackageJSON` guard at parsers.ts:137.

Common situations: Node 20 LTS in CI; mixed ESM/CJS monorepo where the same specifier resolves differently per package; Docker images built on older Node; upgrading Vitest but not the runtime.

Related errors


AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03). Data as JSON: /data/errors/ddad2a821a36190e.json. Report an issue: GitHub.