grafana/k6 · error

getting frame title

Error message

getting frame title: %w

What it means

Thrown by k6 browser's frame.Title(): it evaluates `() => document.title` in the frame, and the evaluation itself failed. That means the frame's execution context was unavailable or destroyed — navigation in flight, frame detached, or page closed.

Solutions

  1. Wait for the page to settle: page.waitForLoadState('domcontentloaded') before title()
  2. Use waitForNavigation around actions that navigate, then read the title
  3. Skip stale frames: check frame.isDetached() if available, or re-list page.frames()
  4. Guard with page.isClosed() in teardown paths

Example fix

// before
const t = page.title();

// after
page.waitForLoadState('domcontentloaded');
const t = page.title();
Defensive patterns

Strategy: try-catch

Validate before calling

page.waitForLoadState('domcontentloaded');
if (page.isClosed()) throw new Error('page closed; cannot read title');

Type guard

const isTitle = (v) => typeof v === 'string';

Try / catch

let title = '';
try {
  title = page.title();
} catch (e) {
  console.log(`title read raced navigation: ${e}`);
  page.waitForLoadState('domcontentloaded');
  title = page.title();
}

Prevention

When it happens

Trigger: frame.title()/page.title() called during navigation (old context destroyed, new one not ready), on a detached frame (iframe removed from DOM), or after the page/target was closed.

Common situations: Asserting the title immediately after page.goto() before commit; reading titles of transient iframes that get removed; iterating page.frames() while the page mutates.

Related errors


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

Appendix: source

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

	}

	return s, true, nil
}

// Timeout will return the default timeout or the one set by the user.
// It's an internal method not to be exposed as a JS API.
func (f *Frame) Timeout() time.Duration {
	return f.defaultTimeout()
}

// Title returns the title of the frame.
func (f *Frame) Title() (string, error) {
	f.log.Debugf("Frame:Title", "fid:%s furl:%q", f.ID(), f.URL())

	js := `() => document.title`
	v, err := f.Evaluate(js)
	if err != nil {
		return "", fmt.Errorf("getting frame title: %w", err)
	}
	s, ok := v.(string)
	if !ok {
		return "", fmt.Errorf("getting frame title: expected string, got %T", v)
	}

	return s, nil
}

// Type text on the first element found matches the selector.
func (f *Frame) Type(selector, text string, popts *FrameTypeOptions) error {
	f.log.Debugf("Frame:Type", "fid:%s furl:%q sel:%q text:%q", f.ID(), f.URL(), selector, text)

	if err := f.typ(selector, text, popts); err != nil {
		return fmt.Errorf("typing %q in %q: %w", text, selector, err)
	}

	applySlowMo(f.ctx)

View on GitHub (pinned to 3fcf5388d7)