{"id":"0e782de344636d3d","repo":"vitest-dev/vitest","slug":"tester-html-file-testerhtmlpath-doesn-t-exist","errorCode":null,"errorMessage":"Tester HTML file \"${testerHtmlPath}\" doesn't exist.","messagePattern":"Tester HTML file \"(.+?)\" doesn't exist\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/browser/src/node/project.ts","lineNumber":52,"sourceCode":"\n  public state: BrowserServerState = new BrowserServerState()\n\n  constructor(\n    public parent: ParentBrowserProject,\n    public project: TestProject,\n    public base: string,\n  ) {\n    this.vitest = project.vitest\n    this.config = project.config\n    this.vite = parent.vite\n\n    // instances can override testerHtmlPath\n    const testerHtmlPath = project.config.browser.testerHtmlPath\n      ? resolve(project.config.root, project.config.browser.testerHtmlPath)\n      : resolve(distRoot, 'client/tester/tester.html')\n    // TODO: when config resolution is rewritten, project and parentProject should be created before the vite server is started\n    if (!existsSync(testerHtmlPath)) {\n      throw new Error(`Tester HTML file \"${testerHtmlPath}\" doesn't exist.`)\n    }\n    this.testerFilepath = testerHtmlPath\n    this.testerHtml = readFile(\n      this.testerFilepath,\n      'utf8',\n    ).then(html => (this.testerHtml = html))\n  }\n\n  private commands = {} as Record<string, BrowserCommand<any, any>>\n\n  public registerCommand<K extends keyof BrowserCommands>(\n    name: K,\n    cb: BrowserCommand<\n      Parameters<BrowserCommands[K]>,\n      ReturnType<BrowserCommands[K]>\n    >,\n  ): void {\n    if (!/^[a-z_$][\\w$]*$/i.test(name)) {","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/browser/src/node/project.ts#L34-L70","documentation":"When `ProjectBrowser` is constructed, it resolves the tester HTML path — either `browser.testerHtmlPath` (resolved against `config.root`) or the built-in `distRoot/client/tester/tester.html` — and checks it exists. If missing, the orchestrator cannot load tests in the browser, so it throws immediately.","triggerScenarios":"Configuring `browser.testerHtmlPath` to a path that doesn't exist; or a corrupt/missing Vitest install where the built-in `tester.html` is absent.","commonSituations":"Typo or wrong relative path in `testerHtmlPath`; pointing at a custom template that was moved/deleted; partial install of `@vitest/browser` (missing `client/tester/tester.html`); building from source and forgetting to run the client build.","solutions":["If you set `browser.testerHtmlPath`, verify the file exists relative to `config.root` (use an absolute path to disambiguate).","Remove the override to use the built-in tester: delete `browser.testerHtmlPath`.","Reinstall `@vitest/browser` (and `vitest`) to restore the built-in `client/tester/tester.html`.","If building from source, run the client build step (`pnpm build` in the browser package)."],"exampleFix":"// before\nexport default defineConfig({\n  test: { browser: { testerHtmlPath: './tester.html' } },\n})\n\n// after — file actually exists, or drop the override\nexport default defineConfig({\n  test: { browser: { enabled: true } },\n})","handlingStrategy":"validation","validationCode":"import { existsSync } from 'node:fs'\nimport { resolve } from 'pathe'\n\nfunction assertTesterHtml(root: string, override?: string): void {\n  const path = override ? resolve(root, override) : undefined\n  if (path && !existsSync(path)) {\n    throw new Error(`Custom browser.testerHtmlPath not found at ${path}`)\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["If overriding testerHtmlPath, point at a tracked file under the project root.","Reinstall @vitest/browser if the built-in tester.html is missing.","Run a config-validate step in CI before launching the browser server."],"tags":["configuration","tester","filesystem","browser"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}