grafana/k6 · error

getting text content of element: unexpected type %T…

Error message

getting text content of element: unexpected type %T (expecting string)

What it means

Internal invariant error in the k6 browser module's ElementHandle.textContent(). The action succeeded and returned a non-nil value, but it was not a Go string (e.g., a sobek.Value or remote-object wrapper). Per the DOM spec element.textContent is string or null, and null is handled separately, so hitting this branch means an unexpected CDP/sobek serialization — an internal/module-level anomaly rather than a script mistake.

Solutions

  1. Upgrade (or roll back) k6 to a known-good release — this is a module defect, not a page condition.
  2. As a workaround, read the text via evaluation: const text = await el.eval('el => el.textContent').
  3. Report to the k6-browser repo with the k6 version and a minimal reproducer.

Example fix

// workaround: bypass textContent()'s internal conversion
const el = await page.waitForSelector('#status');
const text = await el.eval('el => el.textContent');
Defensive patterns

Strategy: fallback

Try / catch

try {
  text = await el.textContent();
} catch (e) {
  if (String(e).includes('unexpected type')) {
    text = await el.eval('n => n.textContent'); // bypass internal conversion
  } else { throw e; }
}

Prevention

When it happens

Trigger: CDP returning a value wrapper the module did not serialize to string (returnByValue path anomaly); version skew between k6 and its embedded browser module; a bug in the module's eval plumbing.

Common situations: Rare; typically after upgrading k6 to a version with a regression, or when a custom k6 build mixes browser module versions.

Related errors


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

Appendix: source

Thrown at internal/js/modules/k6/browser/common/element_handle.go:1540

// The second return value is true if the text content exists, and false otherwise.
func (h *ElementHandle) TextContent() (string, bool, error) {
	textContent := func(apiCtx context.Context, handle *ElementHandle) (any, error) {
		return handle.textContent(apiCtx)
	}
	opts := NewElementHandleBaseOptions(h.DefaultTimeout())
	textContentAction := h.newAction(
		[]string{}, textContent, opts.Force, withRetry, opts.NoWaitAfter, opts.Timeout,
	)
	v, err := call(h.ctx, textContentAction, opts.Timeout)
	if err != nil {
		return "", false, fmt.Errorf("getting text content of element: %w", err)
	}
	if v == nil {
		return "", false, nil
	}
	s, ok := v.(string)
	if !ok {
		return "", false, fmt.Errorf(
			"getting text content of element: unexpected type %T (expecting string)",
			v,
		)
	}

	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 (h *ElementHandle) Timeout() time.Duration {
	return h.DefaultTimeout()
}

// Type scrolls element into view, focuses element and types text.
func (h *ElementHandle) Type(text string, opts *ElementHandleTypeOptions) error {
	typ := func(apiCtx context.Context, handle *ElementHandle) (any, error) {
		return nil, handle.typ(apiCtx, text, KeyboardOptions{})

View on GitHub (pinned to 3fcf5388d7)