{"record":{"id":"24242c5b069679c8","repo":"golang/go","slug":"bufio-writer-returned-negative-count-from-write","errorCode":null,"errorMessage":"bufio: writer returned negative count from Write","messagePattern":"bufio: writer returned negative count from Write","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/bufio/bufio.go","lineNumber":559,"sourceCode":"\n\tfor b.r < b.w {\n\t\t// b.r < b.w => buffer is not empty\n\t\tm, err := b.writeBuf(w)\n\t\tn += m\n\t\tif err != nil {\n\t\t\treturn n, err\n\t\t}\n\t\tb.fill() // buffer is empty\n\t}\n\n\tif b.err == io.EOF {\n\t\tb.err = nil\n\t}\n\n\treturn n, b.readErr()\n}\n\nvar errNegativeWrite = errors.New(\"bufio: writer returned negative count from Write\")\n\n// writeBuf writes the [Reader]'s buffer to the writer.\nfunc (b *Reader) writeBuf(w io.Writer) (int64, error) {\n\tn, err := w.Write(b.buf[b.r:b.w])\n\tif n < 0 {\n\t\tpanic(errNegativeWrite)\n\t}\n\tb.r += n\n\treturn int64(n), err\n}\n\n// buffered output\n\n// Writer implements buffering for an [io.Writer] object.\n// If an error occurs writing to a [Writer], no more data will be\n// accepted and all subsequent writes, and [Writer.Flush], will return the error.\n// After all data has been written, the client should call the\n// [Writer.Flush] method to guarantee all data has been forwarded to","sourceCodeStart":541,"sourceCodeEnd":577,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/bufio/bufio.go#L541-L577","documentation":"Go's bufio package panics with this message inside Reader.writeBuf() when an io.Writer's Write method returns a negative byte count n while draining the Reader's buffer. The io.Writer contract requires 0 <= n <= len(p); a negative value corrupts the read pointer arithmetic, so bufio aborts via panic. This is unrecoverable — it indicates a bug in the writer implementation, not a normal I/O failure.","triggerScenarios":"Triggered when Reader.WriteTo (bufio.go:562-566) calls w.Write(b.buf[b.r:b.w]) and the returned n is < 0. Reachable through Reader.WriteTo, and indirectly via io.Copy when the source is a bufio.Reader. The culprit is always the concrete io.Writer returning a negative count.","commonSituations":"A custom io.Writer returns -1 or another negative number to flag an internal error instead of returning 0 bytes with a non-nil error. A writer wrapper (e.g., a counting/tee writer) that computes n with an underflowing subtraction. Stdlib writers do not produce this; it is characteristic of hand-rolled Writer implementations.","solutions":["Find the concrete io.Writer being written to (the argument to WriteTo / io.Copy target) and fix its Write method to return n >= 0.","If fixing upstream is not possible, wrap the writer so a negative n is clamped to 0 and a synthetic error is returned.","Add a regression test that writes through the suspect writer and verifies n stays non-negative across error paths.","Re-read the io.Writer contract in package io docs: 'Write must return a non-negative number of bytes'."],"exampleFix":"// before — buggy writer returns negative n\nfunc (w *BadWriter) Write(p []byte) (int, error) {\n    if w.closed {\n        return -1, ErrClosed // WRONG\n    }\n    return w.dest.Write(p)\n}\n\n// after — return 0 with the error\nfunc (w *BadWriter) Write(p []byte) (int, error) {\n    if w.closed {\n        return 0, ErrClosed\n    }\n    return w.dest.Write(p)\n}","handlingStrategy":"validation","validationCode":"// Wrap any custom io.Writer before it receives data from a bufio.Reader.\ntype safeWriter struct{ io.Writer }\nfunc (s safeWriter) Write(p []byte) (int, error) {\n    n, err := s.Writer.Write(p)\n    if n < 0 {\n        return 0, fmt.Errorf(\"underlying writer returned negative count %d: %w\", n, err)\n    }\n    return n, err\n}\n// Usage:\n// _, err := bufioReader.WriteTo(safeWriter{myCustomWriter})","typeGuard":"// Contract checker for io.Writer implementations.\nfunc assertWriterContract(w io.Writer) error {\n    n, err := w.Write([]byte(\"x\"))\n    if n < 0 || n > 1 {\n        return fmt.Errorf(\"writer violates contract: n=%d\", n)\n    }\n    return err\n}","tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        if msg, ok := r.(string); ok && strings.Contains(msg, \"negative count from Write\") {\n            // handle: the target writer is buggy\n        }\n        panic(r)\n    }\n}()\n_, err := bufioReader.WriteTo(w)","preventionTips":["Never return a negative n from a custom io.Writer.Write.","Prefer returning (0, err) for any write failure rather than a negative count.","Test custom writers by driving them with io.Copy from a bufio.Reader."],"tags":["go","bufio","io","panic","writer"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T11:17:21.771Z"}