{"record":{"id":"119a50508a421400","repo":"grafana/k6","slug":"steps-must-be-an-integer-got-s","errorCode":null,"errorMessage":"steps must be an integer, got %s","messagePattern":"steps must be an integer, got (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/browser/mouse_mapping.go","lineNumber":164,"sourceCode":"\treturn popts, nil\n}\n\n// parseMouseMoveOptions parses the mouse move options from a Sobek value.\nfunc parseMouseMoveOptions(rt *sobek.Runtime, opts sobek.Value) (*common.MouseMoveOptions, error) {\n\tpopts := common.NewMouseMoveOptions()\n\tif k6common.IsNullish(opts) {\n\t\treturn popts, nil\n\t}\n\n\tobj := opts.ToObject(rt)\n\tfor _, k := range obj.Keys() {\n\t\tif k == \"steps\" {\n\t\t\tv := obj.Get(k)\n\t\t\tswitch v.ExportType().Kind() {\n\t\t\tcase reflect.Int64:\n\t\t\t\tpopts.Steps = v.ToInteger()\n\t\t\tdefault:\n\t\t\t\treturn nil, fmt.Errorf(\"steps must be an integer, got %s\", v.ExportType().Kind())\n\t\t\t}\n\t\t}\n\t}\n\n\treturn popts, nil\n}\n","sourceCodeStart":146,"sourceCodeEnd":171,"githubUrl":"https://github.com/grafana/k6/blob/01ffac6f245854c1b8adc6a69857c76a15f90022/internal/js/modules/k6/browser/browser/mouse_mapping.go#L146-L171","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nconst steps = __ENV.MOVE_STEPS;            // string like \"5\"\nawait page.mouse.move(0, 100, { steps });     // steps must be an integer, got string\n\n// after\nconst steps = Number.parseInt(__ENV.MOVE_STEPS, 10);\nif (!Number.isInteger(steps) || steps < 1) throw new Error('MOVE_STEPS must be a positive integer');\nawait page.mouse.move(0, 100, { steps });","handlingStrategy":"validation","validationCode":"const steps = Number.parseInt(rawSteps, 10);\nif (!Number.isInteger(steps) || steps < 1) {\n  throw new Error(`steps must be a positive integer, got: ${rawSteps}`);\n}\nawait page.mouse.move(x, y, { steps });","typeGuard":"/** @param {unknown} v */\nfunction isValidSteps(v) {\n  return typeof v === 'number' && Number.isInteger(v) && v >= 1;\n}","tryCatchPattern":"try {\n  await page.mouse.move(x, y, { steps });\n} catch (e) {\n  if (String(e).includes('steps must be an integer')) {\n    console.warn(`invalid steps value: ${steps}; using default`);\n    await page.mouse.move(x, y);\n  } else throw e;\n}","preventionTips":["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"],"tags":["k6","browser","mouse","options","type-mismatch"],"backgroundTag":"invalid-option-type","analyzedSha":"01ffac6f245854c1b8adc6a69857c76a15f90022","analyzedAt":"2026-08-18T03:05:52.393Z","contentChangedAt":"2026-08-18T03:05:52.393Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}