grafana/k6 · error

WebSocket endpoint cannot be empty

Error message

WebSocket endpoint cannot be empty

What it means

Before connecting to a remote Chromium over CDP, k6 validates the WebSocket URL in validateWSEndpoint (internal/js/modules/k6/browser/chromium/browser_type.go:155). An empty or whitespace-only value fails immediately with this error instead of attempting a doomed connection. The value comes from the K6_BROWSER_WS_URL environment variable (or the wsURL browser option).

Solutions

  1. Provide a real CDP URL, e.g. K6_BROWSER_WS_URL='ws://localhost:9222/devtools/browser/<guid>'
  2. Fetch the endpoint from the browser's HTTP discovery API: curl http://host:9222/json/version and use its webSocketDebuggerUrl
  3. Unset the variable entirely if you want k6 to launch a local browser instead of connecting remotely
  4. Audit CI env plumbing for empty expansions (use ${VAR:?VAR required} in shells to fail fast)

Example fix

# before
K6_BROWSER_WS_URL= k6 run script.js

# after
K6_BROWSER_WS_URL="$(curl -s http://localhost:9222/json/version | jq -r .webSocketDebuggerUrl)" k6 run script.js
Defensive patterns

Strategy: validation

Validate before calling

# fail fast in the shell before invoking k6
if [ -z "${K6_BROWSER_WS_URL// /}" ]; then
  echo "K6_BROWSER_WS_URL is empty — set it to ws://host:9222/devtools/browser/<guid> or unset it for a local browser" >&2
  exit 1
fi
k6 run script.js

Prevention

When it happens

Trigger: Running with K6_BROWSER_WS_URL defined but empty (K6_BROWSER_WS_URL= k6 run script.js), a whitespace-only value, CI defining the variable with no value, or a docker -e K6_BROWSER_WS_URL flag without an argument; a programmatic BrowserConfig with wsURL left "" while remote connection is selected.

Common situations: CI secrets/variables not populated for the job; docker-compose files where the env var is declared but the service URL is commented out; shell expansion of an unset variable ($REMOTE_WS expanding to empty); switching a pipeline from local to remote browser without updating values.

Related errors


AI-assisted analysis of grafana/k6@8d06114777 (2026-08-18). Data as JSON: /api/errors/20375e15a7ad9f9f. Report an issue: GitHub.

Appendix: source

Thrown at internal/js/modules/k6/browser/chromium/browser_type.go:155

	bp, err := b.connect(ctx, ctx, wsEndpoint, browserOpts, logger)
	if err != nil {
		err = &k6ext.UserFriendlyError{
			Err:     err,
			Timeout: browserOpts.Timeout,
		}
		return nil, fmt.Errorf("%w", err)
	}

	return bp, nil
}

// validateWSEndpoint returns an error if wsEndpoint is not a usable CDP
// WebSocket URL, catching common mistakes (an empty value, a non-ws scheme,
// a missing host, etc.) before we attempt to connect.
func validateWSEndpoint(wsEndpoint string) error {
	if strings.TrimSpace(wsEndpoint) == "" {
		return errors.New("WebSocket endpoint cannot be empty")
	}

	u, err := url.Parse(wsEndpoint)
	if err != nil {
		return fmt.Errorf("invalid WebSocket endpoint %q: %w", wsEndpoint, err)
	}

	if u.Scheme != "ws" && u.Scheme != "wss" {
		return fmt.Errorf(
			"invalid WebSocket endpoint %q: scheme must be ws or wss, got %q", wsEndpoint, u.Scheme,
		)
	}

	if u.Hostname() == "" {
		return fmt.Errorf("invalid WebSocket endpoint %q: host is missing", wsEndpoint)
	}

	return nil

View on GitHub (pinned to 8d06114777)