grafana/k6 · error
browser process ended unexpectedly
Error message
browser process ended unexpectedly
What it means
When launching a local browser, k6 starts the Chrome process, parses its stderr for the DevTools WebSocket URL, and watches the process. If the process's done channel fires before a URL was parsed, the browser died during startup — the parse result is discarded and 'browser process ended unexpectedly' is returned. It is the catch-all for Chrome crashing immediately on launch.
Source
Thrown at internal/js/modules/k6/browser/common/browser_process.go:225
// it. If the process ends abruptly, it will return the first error from stderr.
func parseDevToolsURL(ctx context.Context, cmd command) (_ string, err error) {
parser := &devToolsURLParser{
sc: bufio.NewScanner(cmd.stderr),
}
done := make(chan struct{})
go func() {
for parser.scan() {
}
close(done)
}()
for err == nil {
select {
case <-done:
err = parser.err()
case <-ctx.Done():
err = ContextErr(ctx)
case <-cmd.done:
err = errors.New("browser process ended unexpectedly")
}
}
if parser.url != "" {
err = nil
}
return parser.url, err
}
type devToolsURLParser struct {
sc *bufio.Scanner
errs []error
url string
}
func (p *devToolsURLParser) scan() bool {
if !p.sc.Scan() {View on GitHub (pinned to 93accf6570)
Solutions
- Reproduce outside k6 to see the real stderr: run the exact binary with your flags, e.g. google-chrome --headless=new --no-sandbox --dump-dom about:blank — install whatever libraries it complains about
- When running as root (containers/CI), pass --no-sandbox: K6_BROWSER_ARGS='--no-sandbox' or args in browser options
- Verify the executable is a genuine Chrome/Chromium binary for this architecture (file /usr/bin/chromium)
- Or skip local launch entirely: K6_BROWSER_WS_ENDPOINT=ws://host:9222/... against an already-running browser
Example fix
# before (root container, missing deps)
RUN apk add --no-cache k6
# after
RUN apk add --no-cache k6 chromium nss freetype freetype-dev harfbuzz ca-certificates ttf-liberation
ENV K6_BROWSER_EXECUTABLE_PATH=/usr/bin/chromium-browser \
K6_BROWSER_ARGS="--no-sandbox" Defensive patterns
Strategy: validation
Validate before calling
#!/bin/sh
# Validate the browser launches with the same flags k6 will use before running tests
BIN="${K6_BROWSER_EXECUTABLE_PATH:-$(command -v google-chrome || command -v chromium)}"
[ -n "$BIN" ] || { echo 'no browser binary found' >&2; exit 1; }
exec "$BIN" --headless=new --no-sandbox --user-data-dir=/tmp/k6-preflight --dump-dom about:blank >/dev/null Prevention
- In root containers always pass --no-sandbox via K6_BROWSER_ARGS or the args browser option
- Use a chromium-bundled image and pin it; install the standard dependency set (nss, gbm, atk, cups, gtk)
- Do not pass flags that disable the DevTools endpoint or user-data-dir; k6 needs the WebSocket URL from stderr
- For locked-down runners, switch to K6_BROWSER_WS_ENDPOINT against an external Chrome service
When it happens
Trigger: Chrome exits at startup: missing shared libraries in a slim container (libnss3, libgbm, libatk...); running as root without --no-sandbox; incompatible flags passed via args/K6_BROWSER_ARGUMENTS; wrong-architecture or broken binary; the data dir being unwritable.
Common situations: Minimal Docker images without chromium dependencies; CI running as root; custom Chrome flags copied from Playwright configs; snap-packaged Chromium on Ubuntu; disk-full or read-only profiles.
Related errors
- k6 couldn't detect google chrome or a chromium-supported bro
- browser process shutdown unexpectedly before establishing a
- launching browser: %w
- missing required url
- k6 couldn't detect google chrome or a chromium-supported bro
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/99ad0b30c7ae37e0.
Report an issue: GitHub.