{"record":{"id":"40cc2b16c7d90d9e","repo":"golang/go","slug":"buffer-called-after-scan","errorCode":null,"errorMessage":"Buffer called after Scan","messagePattern":"Buffer called after Scan","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/bufio/scan.go","lineNumber":277,"sourceCode":"\t\ts.err = err\n\t}\n}\n\n// Buffer controls memory allocation by the Scanner.\n// It sets the initial buffer to use when scanning\n// and the maximum size of buffer that may be allocated during scanning.\n// The contents of the buffer are ignored.\n//\n// The maximum token size must be less than the larger of max and cap(buf).\n// If max <= cap(buf), [Scanner.Scan] will use this buffer only and do no allocation.\n//\n// By default, [Scanner.Scan] uses an internal buffer and sets the\n// maximum token size to [MaxScanTokenSize].\n//\n// Buffer panics if it is called after scanning has started.\nfunc (s *Scanner) Buffer(buf []byte, max int) {\n\tif s.scanCalled {\n\t\tpanic(\"Buffer called after Scan\")\n\t}\n\ts.buf = buf[0:cap(buf)]\n\ts.maxTokenSize = max\n}\n\n// Split sets the split function for the [Scanner].\n// The default split function is [ScanLines].\n//\n// Split panics if it is called after scanning has started.\nfunc (s *Scanner) Split(split SplitFunc) {\n\tif s.scanCalled {\n\t\tpanic(\"Split called after Scan\")\n\t}\n\ts.split = split\n}\n\n// Split functions\n","sourceCodeStart":259,"sourceCodeEnd":295,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/bufio/scan.go#L259-L295","documentation":"`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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nfor scanner.Scan() {\n    if scanner.Err() == bufio.ErrTooLong {\n        scanner.Buffer(nil, 1<<20) // panic\n    }\n}\n// after\nscanner := bufio.NewScanner(r)\nscanner.Buffer(make([]byte, 0, 64*1024), 1<<20)\nfor scanner.Scan() { ... }","handlingStrategy":"validation","validationCode":"scanner := bufio.NewScanner(r)\nscanner.Buffer(make([]byte, 0, 64*1024), 1<<20) // before any Scan\n","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Configure Buffer before the scan loop; never inside it.","If you hit ErrTooLong, start over with a new, pre-configured scanner."],"tags":["bufio","scanner","panic","api-ordering","lifecycle"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}