grafana/k6 · error
steps must be an integer, got
Error message
steps must be an integer, got %s
What it means
Thrown by the k6 browser module when parsing the options object of page.mouse.move(x, y, opts). The parser (parseMouseMoveOptions in internal/js/modules/k6/browser/browser/mouse_mapping.go:150-170) requires the 'steps' key to export as a Go int64; any other reflect.Kind (float64, string, bool, object) is rejected with the actual kind name in the message. It is a synchronous argument-validation error: the CDP mouse event is never sent.
Solutions
- Pass an integer literal or a pre-rounded value: page.mouse.move(x, y, { steps: 5 }) or { steps: Math.max(1, Math.round(delta)) }
- If the value comes from configuration, convert it first: const steps = Number.parseInt(rawSteps, 10) and check Number.isInteger(steps) before the call
- Verify the rendered options object (console.log or k6 debug log) to confirm no string or fractional value leaks into steps
Example fix
// before
const steps = __ENV.MOVE_STEPS; // string like "5"
await page.mouse.move(0, 100, { steps }); // steps must be an integer, got string
// after
const steps = Number.parseInt(__ENV.MOVE_STEPS, 10);
if (!Number.isInteger(steps) || steps < 1) throw new Error('MOVE_STEPS must be a positive integer');
await page.mouse.move(0, 100, { steps }); Defensive patterns
Strategy: validation
Validate before calling
const steps = Number.parseInt(rawSteps, 10);
if (!Number.isInteger(steps) || steps < 1) {
throw new Error(`steps must be a positive integer, got: ${rawSteps}`);
}
await page.mouse.move(x, y, { steps }); Type guard
/** @param {unknown} v */
function isValidSteps(v) {
return typeof v === 'number' && Number.isInteger(v) && v >= 1;
} Try / catch
try {
await page.mouse.move(x, y, { steps });
} catch (e) {
if (String(e).includes('steps must be an integer')) {
console.warn(`invalid steps value: ${steps}; using default`);
await page.mouse.move(x, y);
} else throw e;
} Prevention
- Never pass env vars or JSON strings directly as steps — parseInt first
- Round computed steps: Math.max(1, Math.round(delta))
- Centralize mouse option building in one helper that type-checks steps, button, delay and clickCount
When it happens
Trigger: Calling page.mouse.move(100, 200, { steps: 2.5 }) (non-integral number exports as float64); steps passed as a string such as { steps: '5' } (common when the value comes from an env var or JSON config); steps as a boolean or object; computed values like steps: distance/10 where the division yields a fraction.
Common situations: Test data loaded from JSON/environment variables where all values are strings; porting Playwright scripts that compute steps dynamically; dividing pixel distances and forgetting to round; note that plain integer literals (steps: 5) export as int64 and work fine.
Related errors
- clickCount must be an integer, got
- delay must be an integer, got
- double clicking on element
- hovering on element
- parse isChecked options of selector
AI-assisted analysis of grafana/k6@01ffac6f24 (2026-08-18).
Data as JSON: /api/errors/119a50508a421400.
Report an issue: GitHub.
Appendix: source
Thrown at internal/js/modules/k6/browser/browser/mouse_mapping.go:164
return popts, nil
}
// parseMouseMoveOptions parses the mouse move options from a Sobek value.
func parseMouseMoveOptions(rt *sobek.Runtime, opts sobek.Value) (*common.MouseMoveOptions, error) {
popts := common.NewMouseMoveOptions()
if k6common.IsNullish(opts) {
return popts, nil
}
obj := opts.ToObject(rt)
for _, k := range obj.Keys() {
if k == "steps" {
v := obj.Get(k)
switch v.ExportType().Kind() {
case reflect.Int64:
popts.Steps = v.ToInteger()
default:
return nil, fmt.Errorf("steps must be an integer, got %s", v.ExportType().Kind())
}
}
}
return popts, nil
}
View on GitHub (pinned to 01ffac6f24)