grafana/k6 · error

WebSocket endpoint cannot be empty

Error message

WebSocket endpoint cannot be empty

What it means

Before k6 attaches to an existing browser over CDP, validateWSEndpoint sanity-checks the WebSocket URL: it must be non-empty after trimming, parse as a URL, and use the ws:// or wss:// scheme (other failures give their own messages). This specific error means the wsEndpoint value resolved to an empty or whitespace-only string, so connecting would be meaningless.

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 93accf6570)

Solutions

  1. Set a real CDP WebSocket endpoint: K6_BROWSER_WS_ENDPOINT=ws://localhost:9222/devtools/browser/<id> — get the id from curl http://localhost:9222/json/version when Chrome runs with --remote-debugging-port=9222
  2. Make sure the variable is exported in the same shell/step that runs k6 (print it masked in CI logs to confirm it is set)
  3. Trim accidental whitespace/quotes in the value; a quoted value with stray spaces trips the trim check

Example fix

# before
export K6_BROWSER_WS_ENDPOINT=""
k6 run script.js

# after
google-chrome --remote-debugging-port=9222 &
export K6_BROWSER_WS_ENDPOINT="$(curl -s http://localhost:9222/json/version | jq -r .webSocketDebuggerUrl)"
k6 run script.js
Defensive patterns

Strategy: validation

Validate before calling

const endpoint = (process.env.K6_BROWSER_WS_ENDPOINT ?? '').trim();
if (!endpoint) {
  throw new Error('K6_BROWSER_WS_ENDPOINT is empty — start Chrome with --remote-debugging-port and set the ws URL');
}
if (!/^wss?:\/\//.test(endpoint)) {
  throw new Error('K6_BROWSER_WS_ENDPOINT must start with ws:// or wss://');
}

Prevention

When it happens

Trigger: Setting K6_BROWSER_WS_ENDPOINT to an empty value or spaces; building the endpoint from an env var that is not set in this shell/CI step (expands to empty); copying a config template where the endpoint placeholder was never filled in.

Common situations: CI pipelines where the env var is defined in one job but used in another; docker-compose/service definitions with empty-string defaults; scripts that export the endpoint conditionally and skip it on some branches.

Related errors


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