grafana/k6 · error
removing frames recursively: %w
Error message
removing frames recursively: %w
What it means
Thrown by FrameManager.removeFramesRecursively when removing any deeper descendant frame fails (the recursive case of the detach chain; the direct detach failure is error 837). It propagates up through removeChildFramesRecursively (835) and the frameNavigated cleanup (834). Root cause is always the underlying detach error — typically documentHandle.Dispose() or frame-session teardown failing during tree removal.
Source
Thrown at internal/js/modules/k6/browser/common/frame_manager.go:452
func (m *FrameManager) removeChildFramesRecursively(frame *Frame) error {
for _, child := range frame.ChildFrames() {
if err := m.removeFramesRecursively(child); err != nil {
return fmt.Errorf("removing child frames recursively: %w", err)
}
}
return nil
}
func (m *FrameManager) removeFramesRecursively(frame *Frame) error {
for _, child := range frame.ChildFrames() {
m.logger.Debugf("FrameManager:removeFramesRecursively",
"fmid:%d cfid:%v pfid:%v cfname:%s cfurl:%s",
m.ID(), child.ID(), frame.ID(), child.Name(), child.URL())
if err := m.removeFramesRecursively(child); err != nil {
return fmt.Errorf("removing frames recursively: %w", err)
}
}
if err := frame.detach(); err != nil {
return fmt.Errorf("removing frames recursively: detaching frame: %w", err)
}
m.framesMu.Lock()
m.logger.Debugf("FrameManager:removeFramesRecursively:delParentFrame",
"fmid:%d fid:%v fname:%s furl:%s",
m.ID(), frame.ID(), frame.Name(), frame.URL())
delete(m.frames, cdp.FrameID(frame.ID()))
m.framesMu.Unlock()
return nil
}
View on GitHub (pinned to 93accf6570)
Solutions
- Upgrade k6 first — most instances of this chain were race fixes
- Reduce nested-frame churn during the test (block third-party frames) if the app allows
- Capture verbose logs and report with a reproducer if it persists on latest
Defensive patterns
Strategy: retry
Type guard
function isFrameCleanupError(e) {
return e instanceof Error && /removing (child )?frames? recursively/.test(e.message);
} Try / catch
try {
await page.goto(url);
} catch (e) {
if (isFrameCleanupError(e)) { return await page.goto(url); }
throw e;
} Prevention
- Reduce nested-iframe churn during navigations
- Report persistent reproductions with DEBUG logs
When it happens
Trigger: Deeply nested iframes (iframe within iframe) where an inner frame's detach fails while the whole subtree is being removed on navigation or page close; CDP session already invalidated by the browser when k6 tries to dispose handles.
Common situations: Third-party embed trees (ad tech, video players) several levels deep; timing-sensitive failures during rapid navigation sequences; fixed in several later k6 releases.
Related errors
- removing child frames recursively: %w
- can't fetch the page for unknown reason
- execution context %q not found
- removing frames recursively: detaching frame: %w
- frame has been detached 1
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/aa19d73807a0aa3d.
Report an issue: GitHub.