vitest-dev/vitest · critical · Error

Tester HTML file " " doesn't exist.

Error message

Tester HTML file "${testerHtmlPath}" doesn't exist.

What it means

The ProjectBrowser constructor resolves the tester HTML file: either the user-supplied config.browser.testerHtmlPath (resolved against config.root) or the built-in client/tester/tester.html under distRoot. If that file is absent on disk, the tester iframe cannot be served, so construction aborts.

Solutions

  1. If you set browser.testerHtmlPath, verify the file exists with `fs.existsSync(path.resolve(config.root, testerHtmlPath))`.
  2. If using the default, rebuild the browser package (`pnpm build --filter @vitest/browser`) or reinstall from npm to restore dist/client/tester/tester.html.
  3. Check that @vitest/browser is not being resolved from a src directory due to a faulty `exports` map or a yarn link.
  4. Confirm the published package version is intact; downgrade or upgrade if the tarball is known-broken.

Example fix

// before
browser: { testerHtmlPath: './custom-tester.html' } // missing file
// after
browser: { testerHtmlPath: './test/custom-tester.html' } // verified to exist
Defensive patterns

Strategy: validation

Validate before calling

import { existsSync } from 'node:fs'
import { resolve } from 'node:path'
function testerHtmlExists(root: string, custom?: string, distRoot = ''): boolean {
  const p = custom ? resolve(root, custom) : resolve(distRoot, 'client/tester/tester.html')
  return existsSync(p)
}

Prevention

When it happens

Trigger: Setting browser.testerHtmlPath to a path that does not exist; running @vitest/browser from source/CI without having built the client (so distRoot/client/tester/tester.html is missing); a packaging defect where the published tarball omits the tester html.

Common situations: Custom testerHtmlPath with a typo or relative path that resolves outside the project root; running against a linked, un-built @vitest/browser in a monorepo; an npm publish that excluded the dist/client/tester directory.

Related errors


AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11). Data as JSON: /api/errors/0e782de344636d3d. Report an issue: GitHub.

Appendix: source

Thrown at packages/browser/src/node/project.ts:52

  public state: BrowserServerState = new BrowserServerState()

  constructor(
    public parent: ParentBrowserProject,
    public project: TestProject,
    public base: string,
  ) {
    this.vitest = project.vitest
    this.config = project.config
    this.vite = parent.vite

    // instances can override testerHtmlPath
    const testerHtmlPath = project.config.browser.testerHtmlPath
      ? resolve(project.config.root, project.config.browser.testerHtmlPath)
      : resolve(distRoot, 'client/tester/tester.html')
    // TODO: when config resolution is rewritten, project and parentProject should be created before the vite server is started
    if (!existsSync(testerHtmlPath)) {
      throw new Error(`Tester HTML file "${testerHtmlPath}" doesn't exist.`)
    }
    this.testerFilepath = testerHtmlPath
    this.testerHtml = readFile(
      this.testerFilepath,
      'utf8',
    ).then(html => (this.testerHtml = html))
  }

  private commands = {} as Record<string, BrowserCommand<any, any>>

  public registerCommand<K extends keyof BrowserCommands>(
    name: K,
    cb: BrowserCommand<
      Parameters<BrowserCommands[K]>,
      ReturnType<BrowserCommands[K]>
    >,
  ): void {
    if (!/^[a-z_$][\w$]*$/i.test(name)) {

View on GitHub (pinned to 1fa9837ec2)