vitest-dev/vitest · error · Error

Unexpected empty queue

Error message

Unexpected empty queue

What it means

Internal assertion in BrowserPool.runNextTest: a file was just dequeued from this._queue, but this._promise is undefined. The promise is created at the start of runTests and is the resolve/reject handle for the whole batch; finding it absent while a file is being dispatched indicates the pool's internal state machine is inconsistent — treated as a framework bug.

Source

Thrown at packages/vitest/src/node/pools/browser.ts:370

      const isolate = this.project.config.isolate
      // we don't need to cleanup testers if isolation is enabled,
      // because cleanup is done at the end of every test
      if (isolate) {
        this.finishSession(sessionId)
        return
      }

      // we need to cleanup testers first because there is only
      // one iframe and it does the cleanup only after everything is completed
      const orchestrator = this.getOrchestrator(sessionId)
      orchestrator.cleanupTesters()
        .catch(error => this.reject(error))
        .finally(() => this.finishSession(sessionId))
      return
    }

    if (!this._promise) {
      throw new Error(`Unexpected empty queue`)
    }

    const orchestrator = this.getOrchestrator(sessionId)
    debug?.('[%s] run test %s', sessionId, file)

    // warm the transform cache while the iframe is booting so the test
    // file import doesn't wait for the transform; mirrors the URL the
    // tester will request (see `importFile` in the browser runner)
    const fileUrl = `/${/^\w:/.test(file.filepath) ? '@fs/' : ''}${file.filepath}`.replace(/\/+/g, '/')
    void this.project.vite.transformRequest(fileUrl).catch(() => {})

    this.setBreakpoint(sessionId, file.filepath).then(() => {
      // this starts running tests inside the orchestrator
      const testersPromise = this._traces.$(
        `vitest.browser.run`,
        {
          context: this._otel.context,
          attributes: {

View on GitHub (pinned to d568f8ce37)

Solutions

  1. Report as a Vitest bug with a minimal browser test reproduction, focusing on cancel/re-run timing.
  2. Retry — if it was triggered by a one-off browser disconnect it often does not recur.
  3. Avoid triggering manual cancellation while browser tests are mid-run unless necessary.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await vitest.start()
} catch (e) {
  if (e.message === 'Unexpected empty queue') {
    console.error('Browser pool state race — retry; if persistent, report with reproduction.')
  }
  throw e
}

Prevention

When it happens

Trigger: runNextTest is invoked (from a ready-session callback or page-ready callback) after the queue was already cleared/cancelled, so it shifts a file but the _promise was nulled by cancel()/reject()/finishSession at packages/vitest/src/node/pools/browser.ts:369-370.

Common situations: Cancellation racing with the run loop; a test completing and re-triggering runNextTest after the batch promise already resolved; browser disconnect during teardown.

Related errors


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