grafana/k6 · error

delay must be an integer, got

Error message

delay must be an integer, got %s

What it means

Thrown by parseMouseClickOptions (browser/mouse_mapping.go:89) when mouse.click's 'delay' option is not an Int64 kind. Delay (milliseconds between mousedown and mouseup) must be an integer; strings, floats, and booleans are rejected with this message naming the offending reflect.Kind.

Solutions

  1. Use an integer literal: { delay: 100 }.
  2. Round computed delays: { delay: Math.round(thinkTimeMs) }.
  3. Coerce config values: Number(cfg.delay) with an integer check.
  4. Omit delay for an immediate click (delay 0).

Example fix

// before
await page.mouse().click(10, 20, { delay: thinkTime / 3 }); // 33.33

// after
await page.mouse().click(10, 20, { delay: Math.round(thinkTime / 3) });
Defensive patterns

Strategy: type-guard

Validate before calling

if (opts?.delay != null && !Number.isInteger(opts.delay)) throw new Error(`delay must be an integer, got ${typeof opts.delay}`);
await page.mouse().click(x, y, opts);

Type guard

function isIntegerOption(o, key) {
  return o == null || o[key] == null || Number.isInteger(o[key]);
}

Try / catch

try { await page.mouse().click(x, y, opts); } catch (e) { if (/delay must be an integer/.test(e.message)) { await page.mouse().click(x, y, { ...opts, delay: Math.round(Number(opts.delay)) }); } else throw e; }

Prevention

When it happens

Trigger: page.mouse().click(10, 20, { delay: '100' }), { delay: 100.5 }, or { delay: false }. Computed pacing delays that produce fractions are the most common source.

Common situations: Delay from environment variables or JSON scenario config (string-typed); think-time budgets divided across actions yielding floats; delay copied from HTTP response timings.

Related errors


AI-assisted analysis of grafana/k6@01ffac6f24 (2026-08-18). Data as JSON: /api/errors/c620b04748eece03. Report an issue: GitHub.

Appendix: source

Thrown at internal/js/modules/k6/browser/browser/mouse_mapping.go:89

	obj := opts.ToObject(rt)
	for _, k := range obj.Keys() {
		v := obj.Get(k)
		switch k {
		case "button":
			popts.Button = v.String()
		case "clickCount":
			switch v.ExportType().Kind() {
			case reflect.Int64:
				popts.ClickCount = v.ToInteger()
			default:
				return nil, fmt.Errorf("clickCount must be an integer, got %s", v.ExportType().Kind())
			}
		case "delay":
			switch v.ExportType().Kind() {
			case reflect.Int64:
				popts.Delay = v.ToInteger()
			default:
				return nil, fmt.Errorf("delay must be an integer, got %s", v.ExportType().Kind())
			}
		}
	}

	return popts, nil
}

// parseMouseDblClickOptions parses the mouse double click options from a Sobek value.
func parseMouseDblClickOptions(rt *sobek.Runtime, opts sobek.Value) (*common.MouseDblClickOptions, error) {
	popts := common.NewMouseDblClickOptions()
	if k6common.IsNullish(opts) {
		return popts, nil
	}

	obj := opts.ToObject(rt)
	for _, k := range obj.Keys() {
		v := obj.Get(k)
		switch k {

View on GitHub (pinned to 01ffac6f24)