grafana/k6 · critical

internal error while auto-attaching to browser pages

Error message

internal error while auto-attaching to browser pages: %w

What it means

During connect(), initEvents() sends Target.setAutoAttach(autoAttach=true, waitForDebuggerOnStart=true, flatten=true) so every new target (tab, popup, iframe session) streams attachedToTarget events. This error means that CDP command failed, which almost always means the fresh connection is broken or the endpoint does not implement the expected CDP surface.

Solutions

  1. Confirm the browser process survives startup (container logs, exit codes) and fix launch flags/memory if it crashes
  2. Verify the WS URL targets a genuine Chromium browser-level DevTools endpoint
  3. Use a Chromium/headless-shell version supported by the k6 browser module
  4. Re-run with K6_BROWSER_LOG=debug to capture the underlying CDP error text
Defensive patterns

Strategy: retry

Validate before calling

// Verify the endpoint is a Chromium browser-level DevTools endpoint before launch
const res = http.get(`${__ENV.K6_BROWSER_CDP}/json/version`);
const ok = res.status === 200 && /Chrome|HeadlessChrome/.test(res.json('Browser') || '');
if (!ok) throw new Error('Endpoint is not a Chromium DevTools browser');

Try / catch

try {
  const browser = chromium.launch();
} catch (e) {
  if (String(e).includes('auto-attaching to browser pages')) {
    // browser died at startup or endpoint is incompatible:
    // check container logs/OOM, confirm Chromium version, then retry launch
  }
}

Prevention

When it happens

Trigger: The WS connection drops between connect and setAutoAttach; the browser process crashes or is OOM-killed at startup; K6_BROWSER_WS_URL points at a non-Chromium or partial CDP implementation that rejects auto-attach or the flatten option.

Common situations: Remote debugging endpoints behind proxies that kill idle/new sessions; browsers killed by cgroup/OOM limits during test startup; mismatched Chromium/headless-shell versions.

Related errors


AI-assisted analysis of grafana/k6@3fcf5388d7 (2026-08-18). Data as JSON: /api/errors/7a902f4fff3b6a78. Report an issue: GitHub.

Appendix: source

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

				if ev, ok := event.data.(*target.EventAttachedToTarget); ok {
					b.logger.Debugf("Browser:initEvents:onAttachedToTarget", "sid:%v tid:%v", ev.SessionID, ev.TargetInfo.TargetID)
					if err := b.onAttachedToTarget(ev); err != nil {
						k6ext.Panicf(b.vuCtx, "browser is attaching to target: %w", err)
					}
				} else if ev, ok := event.data.(*target.EventDetachedFromTarget); ok {
					b.logger.Debugf("Browser:initEvents:onDetachedFromTarget", "sid:%v", ev.SessionID)
					b.onDetachedFromTarget(ev)
				} else if event.typ == EventConnectionClose {
					b.logger.Debugf("Browser:initEvents:EventConnectionClose", "")
					return
				}
			}
		}
	}()

	action := target.SetAutoAttach(true, true).WithFlatten(true)
	if err := action.Do(cdp.WithExecutor(b.vuCtx, b.conn)); err != nil {
		return fmt.Errorf("internal error while auto-attaching to browser pages: %w", err)
	}

	// Target.setAutoAttach has a bug where it does not wait for new Targets being attached.
	// However making a dummy call afterwards fixes this.
	// This can be removed after https://chromium-review.googlesource.com/c/chromium/src/+/2885888 lands in stable.
	action2 := target.GetTargetInfo()
	if _, err := action2.Do(cdp.WithExecutor(b.vuCtx, b.conn)); err != nil {
		return fmt.Errorf("internal error while getting browser target info: %w", err)
	}

	return nil
}

// connectionOnAttachedToTarget is called when Connection receives an attachedToTarget
// event. Returning false makes the connection release the target instead of
// adopting it. Targets from the connection's own browser context and from
// the default browser context are accepted.
func (b *Browser) connectionOnAttachedToTarget(eva *target.EventAttachedToTarget) bool {

View on GitHub (pinned to 3fcf5388d7)