golang/go · critical
Split called after Scan
Error message
Split called after Scan
What it means
`bufio.Scanner.Split(split)` installs a custom split function. Like `Buffer`, it may only be called before scanning starts; doing so after the first `Scan()` panics via the `s.scanCalled` flag. The default split is `ScanLines`; common alternatives are `ScanWords`, `ScanRunes`, `ScanBytes`, or a user function.
Source
Thrown at src/bufio/scan.go:289
// 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
// ScanBytes is a split function for a [Scanner] that returns each byte as a token.
func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error) {
if atEOF && len(data) == 0 {
return 0, nil, nil
}
return 1, data[0:1], nil
}
var errorRune = []byte(string(utf8.RuneError))
// ScanRunes is a split function for a [Scanner] that returns each
// UTF-8-encoded rune as a token. The sequence of runes returned isView on GitHub (pinned to b6b368adc5)
Solutions
- Set the split function once, immediately after constructing the scanner, before `Scan()`.
- If you must inspect input to choose a split function, do that peek on a separate reader, then create and configure the scanner.
- Centralize scanner construction so lifecycle order is impossible to get wrong.
Example fix
// before
scanner := bufio.NewScanner(r)
scanner.Scan()
scanner.Split(bufio.ScanWords) // panic
// after
scanner := bufio.NewScanner(r)
scanner.Split(bufio.ScanWords)
for scanner.Scan() { ... } Defensive patterns
Strategy: validation
Validate before calling
scanner := bufio.NewScanner(r) scanner.Split(bufio.ScanWords) // before any Scan
Prevention
- Set the split function once, right after NewScanner.
- Peek on a separate reader if you need input to choose a splitter.
When it happens
Trigger: Calling `scanner.Split(...)` inside the scan loop or after the first scan; setting the split function conditionally based on the first token (which requires scanning first).
Common situations: Switching from line-based to word-based splitting after peeking at the first line; refactors that reorder setup; helpers that reconfigure a scanner passed in from elsewhere.
Related errors
- Buffer 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/4c3ae9ebd71631d9.
Report an issue: GitHub.