grafana/k6 · error

lost connection while closing the browser (websocket url: %s

Error message

lost connection while closing the browser (websocket url: %s)

What it means

BrowserProcess.handleClose waits on lostConnection or context completion; if the websocket to the browser dropped and the graceful, browser-initiated shutdown flag was NOT set, it cancels the process context with this error. It usually surfaces as the cause appended by ContextErr on any in-flight browser operation.

Source

Thrown at internal/js/modules/k6/browser/common/browser_process.go:105

	}

	go p.handleClose(ctx)

	return &p, nil
}

func (p *BrowserProcess) handleClose(ctx context.Context) {
	// If we lose connection to the browser and we're not in-progress with clean
	// browser-initiated termination then cancel the context to clean up.
	select {
	case <-p.lostConnection:
	case <-ctx.Done():
	}

	select {
	case <-p.processIsGracefullyClosing:
	default:
		p.cancel(fmt.Errorf("lost connection while closing the browser (websocket url: %s)", p.wsURL))
	}
}

func (p *BrowserProcess) didLoseConnection() {
	close(p.lostConnection)
}

func (p *BrowserProcess) isConnected() bool {
	var ok bool
	select {
	case _, ok = <-p.lostConnection:
	default:
		ok = true
	}
	return ok
}

// GracefulClose triggers a graceful closing of the browser process.

View on GitHub (pinned to 93accf6570)

Solutions

  1. Inspect browser-side logs (run with K6_BROWSER_ENABLE_DEBUGGING=true and capture stderr) for the crash reason.
  2. If the browser is OOM-killed, raise container/host memory or reduce parallel browser scenarios.
  3. Ensure browser.close() is reached in the script (wrap test body so teardown always runs) so shutdown is graceful rather than connection-loss-driven.
  4. Upgrade k6 so its CDP protocol version matches your Chromium build.

Example fix

// before
export default async function () {
  const page = await browser.newPage();
  // ... no explicit close, abrupt exit
}

// after
export default async function () {
  const page = await browser.newPage();
  try {
    // ... test steps
  } finally {
    await page.close();
  }
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await browser.close();
} catch (e) {
  if (/lost connection while closing the browser/.test(String(e))) {
    // browser already dropped; nothing to close — log and move on
    console.warn('browser connection lost during close:', e);
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: The browser process crashes or its DevTools websocket drops while k6 is shutting the browser down (or mid-test), without k6 having initiated a clean Browser.close. The lostConnection channel fires, processIsGracefullyClosing is empty, so cancel() injects this cause.

Common situations: Chrome/Chromium killed by the OS (OOM killer), container runtime killing the browser at test end, remote browser (K6_BROWSER_REMOTE_URL) dropping the connection, version mismatch between k6's CDP layer and an exotic Chromium build.

Related errors


AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15). Data as JSON: /api/errors/e475d4f5d0772158. Report an issue: GitHub.