vitest-dev/vitest · error · Error

Failed to mock '${url}'. See the cause for more information.

Error message

Failed to mock '${url}'. See the cause for more information.

What it means

`NativeModuleMocker.loadManualMock` (`nativeModuleMocker.ts:163`) parses the original module to collect its export names (`collectModuleExports`) and then generates a manual-mock wrapper (`createManualModuleSource`). If either step throws (lexer/parse failure, unusual format), this `Error` wraps the cause. It affects `vi.mock('mod', factory)` — the factory itself isn't run yet; this is the export-shape detection on the real module.

Source

Thrown at packages/vitest/src/runtime/moduleRunner/nativeModuleMocker.ts:163

    if (transformedCode == null) {
      return
    }

    const format = result.format?.startsWith('module') ? 'module' : 'commonjs'
    try {
      // we parse the module with es/cjs-module-lexer to find the original exports -- we assume the same ones are returned from the factory
      // injecting new keys is not supported (and should not be advised anyway)
      const exports = collectModuleExports(moduleId, transformedCode, format)
      const manualMockedModule = createManualModuleSource(moduleId, exports)

      return {
        format: 'module',
        source: manualMockedModule,
        shortCircuit: true,
      }
    }
    catch (cause) {
      throw new Error(`Failed to mock '${url}'. See the cause for more information.`, { cause })
    }
  }

  private processedModules = new Map<string, number>()

  public checkCircularManualMock(url: string): void {
    const filename = url.startsWith('file://') ? fileURLToPath(url) : url
    const id = cleanUrl(normalizeModuleId(filename))
    this.processedModules.set(id, (this.processedModules.get(id) ?? 0) + 1)
    // the module is mocked and requested a second time, let's resolve
    // the factory function that will redefine the exports later
    if (this.originalModulePromises.has(id)) {
      const factoryPromise = this.factoryPromises.get(id)
      this.originalModulePromises.get(id)?.resolve({ __factoryPromise: factoryPromise })
    }
  }

  private originalModulePromises = new Map<string, DeferPromise<any>>()

View on GitHub (pinned to d568f8ce37)

Solutions

  1. Inspect `error.cause` for the specific lexer/parse failure.
  2. Verify the real module loads normally first (import it in a non-test file) — if it can't load, fix the source.
  3. If export collection is fundamentally broken for that module, avoid mocking it via the loader and inject the dependency another way (e.g. dependency injection in the SUT).
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify the real module loads before mocking it.
try {
  await import('mod')
} catch {
  throw new Error('Cannot mock mod: the real module fails to load')
}

Try / catch

try {
  vi.mock('mod', factory)
} catch (e) {
  if (e instanceof Error && /Failed to mock.*See the cause/.test(e.message)) {
    console.error(e.cause)
    // fall back to not mocking, or inject the dependency differently
  } else throw e
}

Prevention

When it happens

Trigger: `vi.mock('mod', () => ({...}))` where `mod` fails export collection — unparseable source, exotic CJS/ESM shape, or a format the lexer doesn't recognize.

Common situations: Manual mocking a module with unusual export patterns; a CJS module with dynamic exports the lexer misses; an `.mjs`/`.cjs` ambiguity.

Related errors


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