grafana/k6 · error

unexpected type %T (expecting string)

Error message

unexpected type %T (expecting string)

What it means

After the innerHTML evaluation succeeds, k6 asserts the CDP result is a Go string; anything non-nil and non-string raises this invariant error. element.innerHTML is a string for real elements, so this fires when the handle points at a node without that property (text node, comment node) or when page scripts tamper with the DOM.

Solutions

  1. Make sure the selector matches an element node: check await el.evaluate(e => e.nodeType === Node.ELEMENT_NODE)
  2. Re-read via evaluation with a String() coercion: await el.evaluate(e => String(e.innerHTML))
  3. Use textContent() instead if you only need the node's content

Example fix

// before
const html = await el.innerHTML(); // handle is a text node

// after
if (!(await el.evaluate(e => e.nodeType === Node.ELEMENT_NODE))) {
  throw new Error('handle is not an element node');
}
const html = await el.innerHTML();
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the handle is an element node before innerHTML()
const isElement = await el.evaluate((e) => e.nodeType === Node.ELEMENT_NODE);
if (!isElement) {
  throw new Error('handle is not an element node; innerHTML is undefined');
}
const html = await el.innerHTML();

Try / catch

try {
  const html = await el.innerHTML();
} catch (e) {
  if (/unexpected type/i.test(String(e.message))) {
    const html = await el.evaluate((e2) => String(e2.innerHTML ?? ''));
  } else throw e;
}

Prevention

When it happens

Trigger: The selector/handle resolved to a text or comment node rather than an element (e.g., a handle obtained from evaluate returning a node); SVG/MathML edge cases; pages overriding innerHTML via Object.defineProperty on prototypes.

Common situations: Handles produced by el.evaluateHandle(...) expressions that return nodes; XPath selectors matching text nodes; instrumented pages that redefine DOM properties. Rare on stock pages.

Related errors


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

Appendix: source

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

// InnerHTML returns the inner HTML of the element.
func (h *ElementHandle) InnerHTML() (string, error) {
	innerHTML := func(apiCtx context.Context, handle *ElementHandle) (any, error) {
		return handle.innerHTML(apiCtx)
	}
	opts := NewElementHandleBaseOptions(h.DefaultTimeout())
	innerHTMLAction := h.newAction(
		[]string{}, innerHTML, opts.Force, withRetry, opts.NoWaitAfter, opts.Timeout,
	)
	v, err := call(h.ctx, innerHTMLAction, opts.Timeout)
	if err != nil {
		return "", fmt.Errorf("getting element's inner HTML: %w", err)
	}

	applySlowMo(h.ctx)

	s, ok := v.(string)
	if !ok {
		return "", fmt.Errorf("unexpected type %T (expecting string)", v)
	}

	return s, nil
}

// InnerText returns the inner text of the element.
func (h *ElementHandle) InnerText() (string, error) {
	innerText := func(apiCtx context.Context, handle *ElementHandle) (any, error) {
		return handle.innerText(apiCtx)
	}
	opts := NewElementHandleBaseOptions(h.DefaultTimeout())
	innerTextAction := h.newAction(
		[]string{}, innerText, opts.Force, withRetry, opts.NoWaitAfter, opts.Timeout.Abs(),
	)
	v, err := call(h.ctx, innerTextAction, opts.Timeout)
	if err != nil {
		return "", fmt.Errorf("getting element's inner text: %w", err)
	}

View on GitHub (pinned to 3fcf5388d7)