{"record":{"id":"da9c4bbb0b6d47c2","repo":"golang/go","slug":"bytes-reader-seek-negative-position","errorCode":null,"errorMessage":"bytes.Reader.Seek: negative position","messagePattern":"bytes\\.Reader\\.Seek: negative position","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/bytes/reader.go","lineNumber":130,"sourceCode":"\treturn nil\n}\n\n// Seek implements the [io.Seeker] interface.\nfunc (r *Reader) Seek(offset int64, whence int) (int64, error) {\n\tr.prevRune = -1\n\tvar abs int64\n\tswitch whence {\n\tcase io.SeekStart:\n\t\tabs = offset\n\tcase io.SeekCurrent:\n\t\tabs = r.i + offset\n\tcase io.SeekEnd:\n\t\tabs = int64(len(r.s)) + offset\n\tdefault:\n\t\treturn 0, errors.New(\"bytes.Reader.Seek: invalid whence\")\n\t}\n\tif abs < 0 {\n\t\treturn 0, errors.New(\"bytes.Reader.Seek: negative position\")\n\t}\n\tr.i = abs\n\treturn abs, nil\n}\n\n// WriteTo implements the [io.WriterTo] interface.\nfunc (r *Reader) WriteTo(w io.Writer) (n int64, err error) {\n\tr.prevRune = -1\n\tif r.i >= int64(len(r.s)) {\n\t\treturn 0, nil\n\t}\n\tb := r.s[r.i:]\n\tm, err := w.Write(b)\n\tif m > len(b) {\n\t\tpanic(\"bytes.Reader.WriteTo: invalid Write count\")\n\t}\n\tr.i += int64(m)\n\tn = int64(m)","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/bytes/reader.go#L112-L148","documentation":"bytes.Reader.Seek returns this error when the computed absolute position would be negative (reader.go:129-131). After resolving offset against whence (start/current/end), the resulting position must be >= 0; a negative position is impossible for a forward-only byte slice, so the Reader rejects it. prevRune has already been cleared by this point.","triggerScenarios":"Triggered when abs < 0 after the whence computation: e.g., Seek(-5, io.SeekStart), Seek(-100, io.SeekCurrent) when fewer than 100 bytes have been read, or Seek(-N, io.SeekEnd) where N exceeds the slice length (reader.go:120-130).","commonSituations":"A relative backward seek (Seek(-n, io.SeekCurrent)) that overshoots the start. Computing an offset from a length that turns out larger than expected. Negative offsets passed through from Range headers or pagination cursors without clamping.","solutions":["Clamp the computed absolute position to >= 0 before calling Seek, or compute offset so abs cannot go negative.","For relative backward seeks, check the current position (via a prior Seek(0, io.SeekCurrent)) and bound n to it.","Validate offsets originating from user input (HTTP Range, cursors) and reject negative start explicitly.","Add a test for backward-seek edge cases near position 0."],"exampleFix":"// before — backward seek can overshoot start\nr.Seek(-n, io.SeekCurrent) // negative position if n > pos\n\n// after — bound n to the current position\ncur, _ := r.Seek(0, io.SeekCurrent)\nif n > cur { n = cur }\nr.Seek(-n, io.SeekCurrent)","handlingStrategy":"validation","validationCode":"// Compute and validate the absolute position before Seek.\nfunc safeSeek(r *bytes.Reader, off int64, whence int) (int64, error) {\n    var abs int64\n    switch whence {\n    case io.SeekStart: abs = off\n    case io.SeekCurrent:\n        cur, _ := r.Seek(0, io.SeekCurrent); abs = cur + off\n    case io.SeekEnd:\n        cur, _ := r.Seek(0, io.SeekEnd); abs = cur + off\n    }\n    if abs < 0 {\n        return 0, fmt.Errorf(\"seek to negative position %d\", abs)\n    }\n    return r.Seek(off, whence)\n}","typeGuard":null,"tryCatchPattern":"pos, err := r.Seek(off, whence)\nif err != nil && strings.Contains(err.Error(), \"negative position\") {\n    // clamp off or bound backward seeks\n}","preventionTips":["Clamp computed absolute positions to >= 0 before Seek.","For backward relative seeks, bound n to the current position.","Validate offsets from user input (Range, cursors) and reject negatives explicitly."],"tags":["go","bytes","reader","seek","validation"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}