grafana/k6 · error

parsing element hover options: %w

Error message

parsing element hover options: %w

What it means

Thrown synchronously by ElementHandle.hover() when its options fail to parse. ElementHandleHoverOptions embeds base-pointer options plus modifiers; in common/element_handle_options.go the only failing steps are exporting 'position' to map[string]float64 and 'modifiers' to []string. The (nil, error) mapping return makes it a synchronous JS exception at call time.

Source

Thrown at internal/js/modules/k6/browser/browser/element_handle_mapping.go:100

				return nil, eh.Focus() //nolint:wrapcheck
			})
		},
		"getAttribute": func(name string) *sobek.Promise {
			return promise(vu, func() (any, error) {
				s, ok, err := eh.GetAttribute(name)
				if err != nil {
					return nil, err //nolint:wrapcheck
				}
				if !ok {
					return nil, nil
				}
				return s, nil
			})
		},
		"hover": func(opts sobek.Value) (*sobek.Promise, error) {
			popts := common.NewElementHandleHoverOptions(eh.DefaultTimeout())
			if err := popts.Parse(vu.Context(), opts); err != nil {
				return nil, fmt.Errorf("parsing element hover options: %w", err)
			}
			return promise(vu, func() (any, error) {
				return nil, eh.Hover(popts) //nolint:wrapcheck
			}), nil
		},
		"innerHTML": func() *sobek.Promise {
			return promise(vu, func() (any, error) {
				return eh.InnerHTML() //nolint:wrapcheck
			})
		},
		"innerText": func() *sobek.Promise {
			return promise(vu, func() (any, error) {
				return eh.InnerText() //nolint:wrapcheck
			})
		},
		"inputValue": func(opts sobek.Value) (*sobek.Promise, error) {
			popts := common.NewElementHandleBaseOptions(eh.DefaultTimeout())
			if err := popts.Parse(vu.Context(), opts); err != nil {

View on GitHub (pinned to 93accf6570)

Solutions

  1. Pass { position: { x: 12, y: 34 } } with plain numbers and modifiers as ['Alt'] etc.
  2. Strip units and coerce with parseInt/Number before building options
  3. Add a small type guard (isPosition/isModifiers) in test setup code for all pointer-based actions
  4. Use try/catch around the call; .catch() will not see this synchronous throw

Example fix

// before
await el.hover({ position: { x: '12px', y: '34px' }, modifiers: 'Alt' });

// after
await el.hover({ position: { x: 12, y: 34 }, modifiers: ['Alt'] });
Defensive patterns

Strategy: type-guard

Validate before calling

if (opts) {
  if (opts.position !== undefined &&
      (typeof opts.position !== 'object' || Array.isArray(opts.position) ||
       !Number.isFinite(Number(opts.position.x)) || !Number.isFinite(Number(opts.position.y)))) {
    throw new Error('hover(): position must be { x: number, y: number }');
  }
  if (opts.modifiers !== undefined &&
      !(Array.isArray(opts.modifiers) && opts.modifiers.every(m => typeof m === 'string'))) {
    throw new Error('hover(): modifiers must be an array of strings');
  }
}

Type guard

function isHoverOpts(o) {
  if (o == null) return true;
  const posOk = o.position === undefined ||
    (typeof o.position === 'object' && !Array.isArray(o.position) &&
     Number.isFinite(Number(o.position.x)) && Number.isFinite(Number(o.position.y)));
  const modOk = o.modifiers === undefined ||
    (Array.isArray(o.modifiers) && o.modifiers.every(m => typeof m === 'string'));
  return posOk && modOk;
}

Try / catch

try {
  await el.hover(opts);
} catch (e) {
  if (/parsing element hover options/.test(String(e.message))) {
    console.log(`fix hover options: ${e.message}`);
  } else throw e;
}

Prevention

When it happens

Trigger: el.hover({ position: 'top' }) or { position: { x: '12px' } } (unit-suffixed string), and { modifiers: 'Alt' } or { modifiers: [null] }. trial/force/timeout never fail; unknown keys are ignored.

Common situations: CSS-style coordinate strings ('12px') copied from stylesheets or design specs; modifiers passed as a single string from a test-data table; dynamically built hover options where position is sometimes undefined and sometimes a serialized string.

Related errors


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