grafana/k6 · error
unexpected type %T (expecting string)
Error message
unexpected type %T (expecting string)
What it means
Internal invariant failure inside ElementHandle.innerHTML(): the evaluation succeeded but the returned remote value did not type-assert to a Go string. element.innerHTML is always a string in a live DOM, so a non-string payload points to a protocol/serialization anomaly or a k6 bug rather than script misuse.
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 93accf6570)
Solutions
- Upgrade k6 to the latest release
- Pin a Chromium version compatible with your k6 release
- Work around with evaluate: const html = await el.evaluate((e) => e.innerHTML)
- Report to k6 with script and browser versions if it persists
Example fix
// before
const html = await el.innerHTML();
// after (workaround)
const html = await el.evaluate((e) => e.innerHTML);
if (typeof html !== 'string') throw new Error('innerHTML not a string'); Defensive patterns
Strategy: validation
Validate before calling
const html = await handle.evaluate((e) => e.innerHTML);
if (typeof html !== 'string') {
throw new Error('innerHTML was not a string');
} Type guard
function isNonEmptyHtml(v) {
return typeof v === 'string';
} Try / catch
try {
return await handle.innerHTML();
} catch (e) {
if (String(e).includes('expecting string')) {
return handle.evaluate((e) => e.innerHTML);
}
throw e;
} Prevention
- Match k6 and Chromium versions
- Use evaluate() as a fallback when protocol serialization misbehaves
- Report reproduction details to k6 maintainers
When it happens
Trigger: Requires the CDP evaluation to return a non-string RemoteObject - essentially only with a Chromium/CDP version mismatched to the k6 release or a k6 regression; not triggerable by normal scripts.
Common situations: Canary/nightly Chromium builds against a stable k6; custom browser executables; k6 versions with known evaluation bugs.
Related errors
- getting attribute %q of element: unexpected type %T (expecti
- unexpected result type while getting document element: %T
- unexpected select element type %T
- evaluating handle of %q: unexpected type %T
- can't fetch the page for unknown reason
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/79057b393a6dfa7f.
Report an issue: GitHub.