{"record":{"id":"62ce36b3951e6286","repo":"grafana/k6","slug":"the-toline-option-must-be-greater-than-or-equal","errorCode":null,"errorMessage":"the 'toLine' option must be greater than or equal to 0; got %d","messagePattern":"the 'toLine' option must be greater than or equal to 0; got (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/experimental/csv/reader.go","lineNumber":153,"sourceCode":"\t\ttoLineSet        = options.ToLine.Valid\n\t\tskipFirstLineSet = options.SkipFirstLine\n\t\tasObjectsEnabled = options.AsObjects.Valid && options.AsObjects.Bool\n\t)\n\n\tif asObjectsEnabled && skipFirstLineSet {\n\t\treturn fmt.Errorf(\"the 'header' option cannot be enabled when 'skipFirstLine' is true\")\n\t}\n\n\tif asObjectsEnabled && fromLineSet && options.FromLine.Int64 > 0 {\n\t\treturn fmt.Errorf(\"the 'header' option cannot be enabled when 'fromLine' is set to a value greater than 0\")\n\t}\n\n\tif fromLineSet && options.FromLine.Int64 < 0 {\n\t\treturn fmt.Errorf(\"the 'fromLine' option must be greater than or equal to 0; got %d\", options.FromLine.Int64)\n\t}\n\n\tif toLineSet && options.ToLine.Int64 < 0 {\n\t\treturn fmt.Errorf(\"the 'toLine' option must be greater than or equal to 0; got %d\", options.ToLine.Int64)\n\t}\n\n\tif fromLineSet && toLineSet && options.FromLine.Int64 >= options.ToLine.Int64 {\n\t\treturn fmt.Errorf(\n\t\t\t\"the 'fromLine' option must be less than the 'toLine' option; got 'fromLine': %d, 'toLine': %d\",\n\t\t\toptions.FromLine.Int64, options.ToLine.Int64,\n\t\t)\n\t}\n\n\treturn nil\n}\n","sourceCodeStart":135,"sourceCodeEnd":165,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/experimental/csv/reader.go#L135-L165","documentation":"validateOptions in the experimental CSV reader rejects a negative toLine (internal/js/modules/k6/experimental/csv/reader.go:153). toLine is the inclusive 0-based stop line; a negative value never selects a valid window and is rejected at construction time with the offending value in the message.","triggerScenarios":"`new csv.Parser(file, { toLine: -1 })` or `csv.parse(file, { toLine: -10 })` - typically a computed bound (e.g. count - 1 with count = 0) or a sentinel value passed through from config.","commonSituations":"Empty input files making count-based arithmetic go negative; copying inclusive/exclusive logic from another language where -1 means 'until the end'.","solutions":["Omit toLine entirely to read to the end of the file","Clamp computed bounds with Math.max(0, n)","Guard against empty selections before building parser options"],"exampleFix":"// before\nconst parser = new csv.Parser(file, { toLine: rowCount - 1 }); // rowCount = 0 -> -1\n\n// after\nconst opts = { toLine: Math.max(0, rowCount - 1) };\nconst parser = new csv.Parser(file, rowCount > 0 ? opts : {});","handlingStrategy":"validation","validationCode":"function clampToLine(o) {\n  if (o.toLine !== undefined && o.toLine < 0) {\n    throw new Error(`toLine must be >= 0, got ${o.toLine}`);\n  }\n  return o;\n}\n// or: if (o.toLine < 0) delete o.toLine; // read to EOF","typeGuard":null,"tryCatchPattern":"try { new csv.Parser(file, opts); } catch (e) { if (/toLine.*greater than or equal/.test(e.message)) { delete opts.toLine; /* retry */ } throw e; }","preventionTips":["Guard count-based bounds against empty inputs (count = 0 makes count-1 negative)","Omit toLine instead of passing -1 to mean 'until the end'"],"tags":["csv","k6","validation","off-by-one"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}