grafana/k6 · error

parsing new frame check options: %w

Error message

parsing new frame check options: %w

What it means

The options object passed to frame.check(selector, opts) failed to parse (frame_mapping.go:22). FrameCheckOptions ultimately parses pointer options; the only field that can currently fail is 'position', which must be a plain object with numeric x and y (element_handle_options.go:189-195 uses rt.ExportTo into map[string]float64).

Source

Thrown at internal/js/modules/k6/browser/browser/frame_mapping.go:22

	"errors"
	"fmt"

	"github.com/grafana/sobek"

	"go.k6.io/k6/v2/internal/js/modules/k6/browser/common"
	k6common "go.k6.io/k6/v2/js/common"
)

// mapFrame to the JS module.
//
//nolint:funlen,gocognit,cyclop
func mapFrame(vu moduleVU, f *common.Frame) mapping {
	rt := vu.Runtime()
	maps := mapping{
		"check": func(selector string, opts sobek.Value) (*sobek.Promise, error) {
			popts := common.NewFrameCheckOptions(f.Timeout())
			if err := popts.Parse(vu.Context(), opts); err != nil {
				return nil, fmt.Errorf("parsing new frame check options: %w", err)
			}
			return promise(vu, func() (any, error) {
				return nil, f.Check(selector, popts) //nolint:wrapcheck
			}), nil
		},
		"childFrames": func() []mapping {
			cfs := f.ChildFrames()
			mcfs := make([]mapping, 0, len(cfs))
			for _, fr := range cfs {
				mcfs = append(mcfs, mapFrame(vu, fr))
			}
			return mcfs
		},
		"click": func(selector string, opts sobek.Value) (*sobek.Promise, error) {
			popts, err := parseFrameClickOptions(vu.Context(), opts, f.Timeout())
			if err != nil {
				return nil, err
			}

View on GitHub (pinned to 93accf6570)

Solutions

  1. Pass position as an object of numbers: { position: { x: 10, y: 20 } } or omit it
  2. If options come from JSON, coerce before the call: { ...opts, position: opts.position && { x: +opts.position.x, y: +opts.position.y } }
  3. Wrap the call in try/catch - parse errors throw synchronously, not as promise rejections

Example fix

// before
frame.check('#accept', { position: 'center' });
// after
frame.check('#accept', { position: { x: 120, y: 40 } });
Defensive patterns

Strategy: type-guard

Validate before calling

// run before frame.check
const opts2 = opts && opts.position
  ? { ...opts, position: { x: Number(opts.position.x), y: Number(opts.position.y) } }
  : opts;

Type guard

function isValidPosition(p) {
  return p == null ||
    (typeof p === 'object' && !Array.isArray(p) &&
      Number.isFinite(Number(p.x)) && Number.isFinite(Number(p.y)));
}
if (!isValidPosition(opts?.position)) throw new Error('position must be {x: number, y: number}');

Try / catch

try {
  const p = frame.check(sel, opts); // parse errors throw synchronously here
  await p;                          // runtime errors reject here
} catch (e) {
  console.error(`check failed for ${sel}: ${e.message}`);
}

Prevention

When it happens

Trigger: Calling frame.check('#cb', { position: 'center' }), { position: [10, 20] } (array, not object), or { position: { x: '10', y: 20 } } (string x) - sobek cannot export the value into map[string]float64 and the error is thrown synchronously before the promise is created.

Common situations: Porting Playwright scripts where position is sometimes given as a tuple or string; dynamic option objects built from JSON configs where numbers arrive as strings; spreads of default objects that accidentally include a malformed position.

Related errors


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