golang/go · critical
Buffer called after Scan
Error message
Buffer called after Scan
What it means
`bufio.Scanner.Buffer(buf, max)` replaces the scanner's internal buffer and max-token size. Calling it after the first `Scan()` would silently change buffering mid-stream, so the package panics via the `s.scanCalled` flag. This is a lifecycle/ordering precondition: configure the scanner fully before entering the scan loop.
Source
Thrown at src/bufio/scan.go:277
s.err = err
}
}
// Buffer controls memory allocation by the Scanner.
// It sets the initial buffer to use when scanning
// and the maximum size of buffer that may be allocated during scanning.
// The contents of the buffer are ignored.
//
// The maximum token size must be less than the larger of max and cap(buf).
// If max <= cap(buf), [Scanner.Scan] will use this buffer only and do no allocation.
//
// By default, [Scanner.Scan] uses an internal buffer and sets the
// maximum token size to [MaxScanTokenSize].
//
// Buffer panics if it is called after scanning has started.
func (s *Scanner) Buffer(buf []byte, max int) {
if s.scanCalled {
panic("Buffer called after Scan")
}
s.buf = buf[0:cap(buf)]
s.maxTokenSize = max
}
// Split sets the split function for the [Scanner].
// The default split function is [ScanLines].
//
// Split panics if it is called after scanning has started.
func (s *Scanner) Split(split SplitFunc) {
if s.scanCalled {
panic("Split called after Scan")
}
s.split = split
}
// Split functions
View on GitHub (pinned to b6b368adc5)
Solutions
- Call `scanner.Buffer(make([]byte, 0, 64*1024), maxLen)` before the first `Scan()`.
- If you already hit `ErrTooLong`, discard that scanner and create a new one configured with a larger max before scanning.
- Lift all scanner configuration (`Buffer`, `Split`) into a single `newScanner(r)` helper.
Example fix
// before
for scanner.Scan() {
if scanner.Err() == bufio.ErrTooLong {
scanner.Buffer(nil, 1<<20) // panic
}
}
// after
scanner := bufio.NewScanner(r)
scanner.Buffer(make([]byte, 0, 64*1024), 1<<20)
for scanner.Scan() { ... } Defensive patterns
Strategy: validation
Validate before calling
scanner := bufio.NewScanner(r) scanner.Buffer(make([]byte, 0, 64*1024), 1<<20) // before any Scan
Prevention
- Configure Buffer before the scan loop; never inside it.
- If you hit ErrTooLong, start over with a new, pre-configured scanner.
When it happens
Trigger: Calling `Buffer` inside the `for scanner.Scan()` loop; calling it after a first Scan in a setup helper; refactoring that moved the Buffer call below the first Scan.
Common situations: Reading very long lines: developer first runs Scan, hits `ErrTooLong`, then tries to call Buffer to raise the limit — but on the same scanner instance, which has already started.
Related errors
- Split called after Scan
- bufio: reader returned negative count from Read
- bufio: writer returned negative count from Write
- bufio.Scanner: token too long
- bufio.Scanner: SplitFunc returns negative advance count
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/40cc2b16c7d90d9e.
Report an issue: GitHub.