grafana/k6 · error

getting text content of %q: %w

Error message

getting text content of %q: %w

What it means

Frame.TextContent() wraps the internal action as 'getting text content of "<selector>": <cause>'. The cause is typically a wait timeout (element never reached the attached state within opts.timeout), a strict-mode ambiguity, or a frame/context failure during evaluation.

Source

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

		opts.Force, withRetry, opts.NoWaitAfter, opts.Timeout,
	)

	if _, err := call(f.ctx, act, opts.Timeout); err != nil {
		return errorFromDOMError(err)
	}

	return nil
}

// TextContent returns the textContent attribute of the first element found
// that matches the selector. The second return value is true if the returned
// text content is not null or empty, and false otherwise.
func (f *Frame) TextContent(selector string, popts *FrameTextContentOptions) (string, bool, error) {
	f.log.Debugf("Frame:TextContent", "fid:%s furl:%q sel:%q", f.ID(), f.URL(), selector)

	v, ok, err := f.textContent(selector, popts)
	if err != nil {
		return "", false, fmt.Errorf("getting text content of %q: %w", selector, err)
	}

	return v, ok, nil
}

func (f *Frame) textContent(selector string, opts *FrameTextContentOptions) (string, bool, error) {
	TextContent := func(apiCtx context.Context, handle *ElementHandle) (any, error) {
		return handle.textContent(apiCtx)
	}
	act := f.newAction(
		selector, DOMElementStateAttached, opts.Strict, TextContent,
		[]string{}, false, withRetry, true, opts.Timeout,
	)
	v, err := call(f.ctx, act, opts.Timeout)
	if err != nil {
		return "", false, errorFromDOMError(err)
	}
	if v == nil {

View on GitHub (pinned to 93accf6570)

Solutions

  1. Prefer waiting for the content: const el = await frame.waitForSelector(sel); then el.textContent().
  2. Fix the selector to match exactly one node, or pass { strict: false } intentionally.
  3. Increase the timeout: frame.textContent(sel, { timeout: 60_000 }).
  4. Check page/frame state (isClosed/isDetached) if the failure is instant rather than after a timeout.

Example fix

// before
const t = await frame.textContent('.status'); // element not rendered yet

// after
const el = await frame.waitForSelector('.status');
const t = await el.textContent();
Defensive patterns

Strategy: try-catch

Validate before calling

const el = await frame.waitForSelector(sel, { state: 'attached' });
if (!el) throw new Error('element not attached');

Try / catch

try { return await frame.textContent(sel, { timeout: 60_000 }); }
catch (e) { if (/getting text content of/.test(e.message)) { return null; /* treat as absent */ } throw e; }

Prevention

When it happens

Trigger: frame.textContent(sel) where the selector never matches within the timeout (default 30s); selector matches multiple elements with strict mode; frame navigated or detached while reading; page closed.

Common situations: Reading text of dynamically rendered content without waiting; wrong selector after a UI update; CI slowness making the default timeout too short.

Related errors


AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15). Data as JSON: /api/errors/b3d4fdb4f885f6c7. Report an issue: GitHub.