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

  1. Call `scanner.Buffer(make([]byte, 0, 64*1024), maxLen)` before the first `Scan()`.
  2. If you already hit `ErrTooLong`, discard that scanner and create a new one configured with a larger max before scanning.
  3. 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

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


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/40cc2b16c7d90d9e. Report an issue: GitHub.