grafana/k6 · error
setting window bounds: %w
Error message
setting window bounds: %w
What it means
Only in headed mode (hasUIWindow), after viewport emulation k6 resizes the actual OS window with Browser.setWindowBounds so the visible window matches the emulated viewport plus OS-specific insets. This error means that window-resize command failed. In headless mode this code path is skipped entirely.
Source
Thrown at internal/js/modules/k6/browser/common/frame_session.go:1272
WithScreenWidth(screen.Width).
WithScreenHeight(screen.Height)
if err := action.Do(cdp.WithExecutor(fs.ctx, fs.session)); err != nil {
return fmt.Errorf("emulating viewport: %w", err)
}
if fs.hasUIWindow {
// add an inset to viewport depending on the operating system.
// this won't add an inset if we're running in headless mode.
viewport = viewport.recalculateInset(
fs.page.browserCtx.browser.browserOpts.Headless,
runtime.GOOS,
)
action2 := browser.SetWindowBounds(fs.windowID, &browser.Bounds{
Width: viewport.Width,
Height: viewport.Height,
})
if err := action2.Do(cdp.WithExecutor(fs.ctx, fs.session)); err != nil {
return fmt.Errorf("setting window bounds: %w", err)
}
}
return nil
}
func (fs *FrameSession) executionContextForID(
executionContextID cdpruntime.ExecutionContextID,
) (*ExecutionContext, error) {
fs.contextIDToContextMu.Lock()
defer fs.contextIDToContextMu.Unlock()
if exc, ok := fs.contextIDToContext[executionContextID]; ok {
return exc, nil
}
return nil, fmt.Errorf("no execution context found for id: %v", executionContextID)
}View on GitHub (pinned to 93accf6570)
Solutions
- Run headless in CI, or provide a real display/xvfb when headed mode is required
- Do not close or minimize the window between page creation and viewport application
- Retry once; if the emulated viewport already applied, the window bounds step is cosmetic and a retry usually succeeds
- Upgrade k6: window bounds and inset handling have improved across releases
Example fix
// before: headed CI without display
const browser = chromium.launch({ headless: false });
const page = await browser.newPage({ viewport: { width: 1280, height: 720 } });
// after: headless for CI
const browser = chromium.launch({ headless: true });
const page = await browser.newPage({ viewport: { width: 1280, height: 720 } }); Defensive patterns
Strategy: validation
Validate before calling
// avoid the headed window-resize path entirely in CI
const headless = __ENV.CI === 'true';
const browser = chromium.launch({ headless }); Try / catch
try { await page.setViewport(...); }
catch (e) { if (!/setting window bounds/.test(String(e.message))) throw e; /* retry or continue */ } Prevention
- Run headless unless you explicitly need a visible window
- For headed runs, provide a real display or xvfb
- Do not minimize or close the window between page creation and viewport application
When it happens
Trigger: Running with headless: false together with a viewport option; the window ID became invalid (window closed between page creation and resize), the window is minimized/fullscreen so it cannot be resized, or the DevTools connection dropped before the command was executed.
Common situations: Local headed debugging with an explicit viewport; CI jobs accidentally running headed without a display server or window manager; desktop environments denying programmatic resize; closing the window manually mid-test.
Related errors
- emulating viewport: %w
- WebSocket endpoint cannot be empty
- can't fetch the page for unknown reason
- errorText
- parent frame has been detached
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/838608cf0152f625.
Report an issue: GitHub.