vitest-dev/vitest · error · Error

Cannot parse '${filename}' because "module.stripTypeScriptTy

Error message

Cannot parse '${filename}' because "module.stripTypeScriptTypes" is not supported. Module mocking requires Node.js 22.15 or higher. This is NOT a bug of Vitest.

What it means

Vitest's mocker must statically enumerate a mocked module's exports, which for TypeScript sources requires stripping types via Node's `module.stripTypeScriptTypes` (added in Node 22.15). On an older Node runtime that API is `undefined`, so `transformCode` in parsers.ts refuses to guess and throws rather than silently producing a broken automock.

Source

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

export async function initSyntaxLexers(): Promise<void> {
  await Promise.all([
    initCjsLexer(),
    initModuleLexer,
  ])
}

const isTransform = process.execArgv.includes('--experimental-transform-types')
  || process.env.NODE_OPTIONS?.includes('--experimental-transform-types')

export function transformCode(code: string, filename: string): string {
  const ext = extname(filename.split('?')[0])
  const isTs = ext === '.ts' || ext === '.cts' || ext === '.mts'
  if (!isTs) {
    return code
  }
  if (!module.stripTypeScriptTypes) {
    throw new Error(`Cannot parse '${filename}' because "module.stripTypeScriptTypes" is not supported. Module mocking requires Node.js 22.15 or higher. This is NOT a bug of Vitest.`)
  }
  return module.stripTypeScriptTypes(code, { mode: isTransform ? 'transform' : 'strip' })
}

const cachedFileExports = new Map<string, string[]>()

export function collectModuleExports(
  filename: string,
  code: string,
  format: 'module' | 'commonjs',
  exports: string[] = [],
): string[] {
  if (format === 'module') {
    const [imports_, exports_] = parseModuleSyntax(code, filename)
    const fileExports = [...exports_.map(p => p.n)]
    imports_.forEach(({ ss: start, se: end, n: name }) => {
      const substring = code.substring(start, end).replace(/ +/g, ' ')
      if (name && substring.startsWith('export *') && !substring.startsWith('export * as')) {

View on GitHub (pinned to d568f8ce37)

Solutions

  1. Upgrade Node.js to 22.15 or newer (verify with `node -e "console.log(typeof require('module').stripTypeScriptTypes)"`).
  2. If you cannot upgrade, supply a full factory so Vitest skips export analysis: `vi.mock('./mod.ts', () => ({ default: stub }))`.
  3. Mock the compiled `.js`/`.mjs` output instead of the `.ts` source so type stripping is unnecessary.

Example fix

// before
vi.mock('./config.ts')

// after (Node < 22.15 workaround)
vi.mock('./config.ts', () => ({
  default: { port: 3000, host: 'localhost' },
}))
Defensive patterns

Strategy: validation

Validate before calling

import module from 'node:module'

const canStripTs = typeof module.stripTypeScriptTypes === 'function'
if (!canStripTs) {
  console.warn(
    `vi.mock of TypeScript modules needs Node >= 22.15; current is ${process.version}. ` +
    `Provide an explicit factory or upgrade Node.`,
  )
}

Prevention

When it happens

Trigger: Calling `vi.mock('./mod.ts')` (or letting Vitest automock a `.ts`/`.cts`/`.mts` dependency) while running on Node older than 22.15, where the `!module.stripTypeScriptTypes` guard at parsers.ts:25 is true.

Common situations: CI pinned to Node 20 LTS; local dev on Node 18/20; Docker base image lagging; upgrading Vitest without bumping the Node engines; monorepos whose root `engines.node` still allows v20.

Related errors


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