grafana/k6 · error
checking is in viewport: unexpected type %T
Error message
checking is %q in viewport: unexpected type %T
What it means
Internal invariant error in k6 browser's frame.isInViewport: after the action succeeds, the value returned by the CDP evaluation must be a Go bool; the type assertion v.(bool) failed. It signals an unexpected protocol/serialization result, not a user-input problem.
Solutions
- Re-run the test once to rule out a transient CDP glitch
- Check for a k6/Chromium version mismatch and align versions (k6 >= the version that shipped your browser module)
- Report it as a k6 bug at https://github.com/grafana/k6/issues with the script and k6 version
- Work around by checking visibility and bounding box via elementHandle.boundingBox() instead
Defensive patterns
Strategy: try-catch
Try / catch
try {
const inVp = frame.isInViewPort ? page.$eval(sel, el => { /* bbox ratio check */ return true; }) : false;
} catch (e) {
console.log(`viewport check failed (likely internal): ${e}`);
} Prevention
- Keep k6 and its bundled Chromium versions matched and current
- Pin the k6 version in CI so protocol behavior cannot drift silently
When it happens
Trigger: Calling elementHandle.../page.isInViewPort-style internal path where the in-viewport ratio evaluation returns a non-bool remote value — realistically only from a Chromium/k6 version mismatch or an internal bug, since the evaluated JS always produces a boolean.
Common situations: Upgrading k6 or the bundled Chromium to mismatched versions; virtually never seen in normal test runs because the injected script returns a boolean by construction.
Related errors
- unexpected select element type %T
- an error occurred communicating with the provisioning API
- checking element is in viewport: unexpected type %T
- Error while parsing selector
- failed to authenticate with k6 Cloud
AI-assisted analysis of grafana/k6@3fcf5388d7 (2026-08-18).
Data as JSON: /api/errors/bbdc3af23c473c19.
Report an issue: GitHub.
Appendix: source
Thrown at internal/js/modules/k6/browser/common/frame.go:1602
func (f *Frame) isInViewport(selector string, opts *FrameIsInViewportOptions) (bool, error) {
isInViewport := func(apiCtx context.Context, handle *ElementHandle) (any, error) {
v, err := handle.isInViewport(apiCtx, opts.Ratio)
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, isInViewport, []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 in viewport: unexpected type %T", selector, v)
}
return bv, nil
}
// ID returns the frame id.
func (f *Frame) ID() string {
f.propertiesMu.RLock()
defer f.propertiesMu.RUnlock()
return f.id.String()
}
// Locator creates and returns a new locator for this frame.
func (f *Frame) Locator(selector string, opts *LocatorOptions) *Locator {
f.log.Debugf("Frame:Locator", "fid:%s furl:%q selector:%q opts:%+v", f.ID(), f.URL(), selector, opts)
return NewLocator(f.ctx, opts, selector, f, f.log)View on GitHub (pinned to 3fcf5388d7)