grafana/k6 · error

checking is %q checked: unexpected type %T

Error message

checking is %q checked: unexpected type %T

What it means

After the isChecked action succeeds, k6 type-asserts the action's return value to bool. If the internal pipeline produced anything else (nil, string), the assertion fails. This is an internal invariant violation — the DOM action contract (bool return) was broken, and it usually indicates a module bug or a highly unusual CDP state, not user error.

Source

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

func (f *Frame) isChecked(selector string, opts *FrameIsCheckedOptions) (bool, error) {
	isChecked := func(apiCtx context.Context, handle *ElementHandle) (any, error) {
		v, err := handle.isChecked(apiCtx, 0) // Zero timeout when checking state
		if errors.Is(err, ErrTimedOut) {      // We don't care about timeout errors here!
			return v, nil
		}
		return v, err
	}
	act := f.newAction(
		selector, DOMElementStateAttached, opts.Strict, isChecked, []string{}, false, withRetry, true, opts.Timeout,
	)
	v, err := call(f.ctx, act, opts.Timeout)
	if err != nil {
		return false, errorFromDOMError(err)
	}

	bv, ok := v.(bool)
	if !ok {
		return false, fmt.Errorf("checking is %q checked: unexpected type %T", selector, v)
	}

	return bv, nil
}

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

	js := `() => {
		let content = '';
		if (document.doctype) {
			content = new XMLSerializer().serializeToString(document.doctype);
		}
		if (document.documentElement) {
			content += document.documentElement.outerHTML;
		}
		return content;

View on GitHub (pinned to 93accf6570)

Solutions

  1. Wrap in try-catch and fall back to reading state via evaluate (input.checked).
  2. Ensure the element stays attached (waitForSelector visible) before isChecked.
  3. Upgrade k6 to the latest patch — internal assertion failures are treated as module bugs.

Example fix

// before
const ok = frame.isChecked('#agree');

// after
let ok;
try {
  ok = frame.isChecked('#agree');
} catch (e) {
  console.warn('isChecked failed, falling back:', e.message);
  ok = frame.evaluate('() => document.querySelector("#agree").checked');
}
Defensive patterns

Strategy: try-catch

Validate before calling

await frame.waitForSelector(sel, { state: 'attached', timeout: 30000 });

Type guard

const isBool = (v) => typeof v === 'boolean';

Try / catch

let ok;
try {
  ok = frame.isChecked(sel);
} catch (e) {
  ok = frame.evaluate('(s) => !!document.querySelector(s)?.checked', sel);
}
if (!isBool(ok)) throw new Error('unchecked state could not be read');

Prevention

When it happens

Trigger: handle.isChecked() returning a non-boolean (e.g. nil remote object) for detached/odd elements; internal refactor changing the action return type in a specific k6 version.

Common situations: Element detaches exactly between wait success and state read; regression in a k6 browser module release; sporadic under heavy load timing.

Related errors


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