grafana/k6 · warning
internal error while removing binding from page: %w
Error message
internal error while removing binding from page: %w
What it means
During Page.Close, k6 attempts to remove the internal web-vitals binding from the page via runtime.RemoveBinding before closing the target. This error is recorded (the close still proceeds) when that CDP call fails, typically because the page crashed, already navigated away destroying the binding world, or the teardown timeout context expired. It is joined with other close errors and surfaced from page.close().
Source
Thrown at internal/js/modules/k6/browser/common/page.go:1007
Object.defineProperty(document, 'visibilityState', {value: 'hidden', configurable: true});
Object.defineProperty(document, 'hidden', {value: true, configurable: true});
document.dispatchEvent(new Event('visibilitychange'));
}`
if _, err := p.MainFrame().EvaluateWithContext(teardownTimeoutCtx, v); err != nil {
p.logger.Warnf("Page:Close", "failed to trigger visibilitychange for web vitals: %v", err)
}
keyDown := input.DispatchKeyEvent(input.KeyDown).WithKey("Escape")
if err := keyDown.Do(cdp.WithExecutor(teardownTimeoutCtx, p.session)); err != nil {
p.logger.Warnf("Page:Close", "failed to dispatch keydown for web vitals: %v", err)
}
var closeErrs []error
add := runtime.RemoveBinding(webVitalBinding)
if err := add.Do(cdp.WithExecutor(teardownTimeoutCtx, p.session)); err != nil {
// continue so that we can shutdown the page even if we fail to remove the binding.
closeErrs = append(closeErrs, fmt.Errorf("internal error while removing binding from page: %w", err))
}
err := target.CloseTarget(p.targetID).Do(cdp.WithExecutor(teardownTimeoutCtx, p.session))
if err != nil && !errors.Is(err, context.Canceled) {
// When a close target command is sent to the browser via CDP,
// the browser will start to cleanup and the first thing it
// will do is return a target.EventDetachedFromTarget, which in
// our implementation will close the session connection (this
// does not close the CDP websocket, just removes the session
// so no other CDP calls can be made with the session ID).
// This can result in the session's context being closed while
// we're waiting for the response to come back from the browser
// for this current command (it's racey).
closeErrs = append(closeErrs, fmt.Errorf("closing a page: %w", err))
}
// Start the teardown of the page's resources (FrameSessions, NetworkManagers, etc)
// and wait for them to finish their teardown. This allows for a graceful cleanupView on GitHub (pinned to 93accf6570)
Solutions
- Close pages before closing the browser or ending the iteration (use a try/finally block)
- Increase the browserContext timeout option if teardown is being cut short
- Investigate renderer crashes (browser logs, --disable-dev-shm-usage in a Docker host) if a page is dying before close
- Treat as non-fatal if the page close otherwise succeeded and no further operations use that page
Example fix
// before
// page left open, iteration ends, teardown races
// after
const page = await context.newPage();
try {
await page.goto('https://example.com/');
} finally {
await page.close().catch(e => console.warn('close warning:', e.message));
} Defensive patterns
Strategy: try-catch
Validate before calling
null
Try / catch
try {
await page.close();
} catch (e) {
if (/removing binding from page/.test(e.message)) { /* non-fatal teardown noise */ }
else throw e;
} Prevention
- Always close pages explicitly before the browser or iteration ends (try/finally)
- Set a generous browserContext timeout so teardown is not cut short
- Watch for earlier renderer-crash events; fix those to avoid close-time binding failures
When it happens
Trigger: page.close() on a page whose renderer already crashed (OOM, segfault), a page mid-navigation when the teardown timeout (browserContext timeout) fires, or a page whose target the browser already destroyed.
Common situations: Heavy pages that OOM the renderer; very short timeouts on the browser context causing teardown to race; closing pages after browser.close() was already initiated; 'page crashed' events earlier in the log.
Related errors
- closing a page: %w
- internal error while adding binding to page: %w
- WebSocket endpoint cannot be empty
- can't fetch the page for unknown reason
- cannot close context as none is active in browser
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/e900b0e74a00b938.
Report an issue: GitHub.