vitest-dev/vitest · warning · Error

Failed to fetch browser runner HTML from ${browserUrl}

Error message

Failed to fetch browser runner HTML from ${browserUrl}

What it means

This error is internal to Vitest's own development workflow. The devUiScriptPlugin in packages/ui/vite.config.ts fetches the browser test runner's HTML page when the BROWSER_DEV environment variable is set, so the UI dev server can inject the runner's bootstrap script. If the fetch returns a non-OK HTTP status, this error fires. End users of Vitest never hit this; only contributors running the UI dev server in browser-dev mode do.

Source

Thrown at packages/ui/vite.config.ts:84

    outDir: './dist/client',
  },
})

function devUiScriptPlugin(): Plugin {
  const BROWSER_SCRIPT_RE = /<script type="module">([\s\S]*?window\.__vitest_browser_runner__\s*=\s*\{[\s\S]*?window\.VITEST_API_TOKEN\s*=[\s\S]*?)<\/script>/

  const browserUrl = `http://localhost:${process.env.BROWSER_DEV_PORT || '63315'}/__vitest_test__/`

  return {
    name: 'dev-ui-script',
    apply(_config, env) {
      return env.command === 'serve' && env.mode !== 'test'
    },
    async transformIndexHtml() {
      if (process.env.BROWSER_DEV) {
        const response = await fetch(browserUrl)
        if (!response.ok) {
          throw new Error(`Failed to fetch browser runner HTML from ${browserUrl}`)
        }
        const browserHtml = await response.text()
        const browserScript = browserHtml.match(BROWSER_SCRIPT_RE)?.[1]
        if (!browserScript) {
          throw new Error('Failed to extract browser runner state from the response')
        }
        return [
          {
            tag: 'script',
            attrs: { type: 'module' },
            children: browserScript,
            injectTo: 'head-prepend',
          },
        ]
      }

      const token = resolveApiToken(process.cwd()).token
      return [

View on GitHub (pinned to 1fa9837ec2)

Solutions

  1. Start the Vitest browser server first so it is listening on the expected port, then start the UI dev server.
  2. Verify BROWSER_DEV_PORT matches the port the browser runner actually uses.
  3. Unset BROWSER_DEV if you are not doing browser-runner UI integration work.
Defensive patterns

Strategy: validation

Validate before calling

// internal dev workflow — before starting UI dev server with BROWSER_DEV:
const port = process.env.BROWSER_DEV_PORT || '63315'
try {
  const res = await fetch(`http://localhost:${port}/__vitest_test__/`)
  if (!res.ok) throw new Error('browser runner not ready')
} catch { console.warn('Start the browser runner first') }

Prevention

When it happens

Trigger: Running `pnpm dev` for the UI package with BROWSER_DEV set but no Vitest browser server listening at the configured port (BROWSER_DEV_PORT or default 63315), or the server returning an error status.

Common situations: Contributor forgot to start the browser test server before starting the UI dev server; wrong BROWSER_DEV_PORT; firewall/proxy blocking localhost fetch.

Related errors


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