{"record":{"id":"72b86ea9007d031b","repo":"gravitational/teleport","slug":"internal-buffer-has-grown-too-big","errorCode":null,"errorMessage":"internal buffer has grown too big","messagePattern":"internal buffer has grown too big","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/client/escape/reader.go","lineNumber":44,"sourceCode":"\t\"sync\"\n)\n\nconst (\n\treaderBufferLimit = 10 * 1024 * 1024 // 10MB\n\n\t// Note: on a raw terminal, \"\\r\\n\" is needed to move a cursor to the start\n\t// of next line.\n\thelpText = \"\\r\\ntsh escape characters:\\r\\n  ~? - display a list of escape characters\\r\\n  ~. - disconnect\\r\\n\"\n)\n\nvar (\n\t// ErrDisconnect is returned when the user has entered a disconnect\n\t// sequence, requesting connection to be interrupted.\n\tErrDisconnect = errors.New(\"disconnect escape sequence detected\")\n\t// ErrTooMuchBufferedData is returned when the Reader's internal buffer has\n\t// filled over 10MB. Either the consumer of Reader can't keep up with the\n\t// data or it's entirely stuck and not consuming the data.\n\tErrTooMuchBufferedData = errors.New(\"internal buffer has grown too big\")\n)\n\n// Reader is an io.Reader wrapper that catches OpenSSH-like escape sequences in\n// the input stream. See NewReader for more info.\n//\n// Reader is safe for concurrent use.\ntype Reader struct {\n\tinner        io.Reader\n\tout          io.Writer\n\tonDisconnect func(error)\n\tbufferLimit  int\n\n\t// cond protects buf and err and also announces to blocked readers that\n\t// more data is available.\n\tcond sync.Cond\n\tbuf  []byte\n\terr  error\n}","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/gravitational/teleport/blob/1283425b60ec5f60d509ba4c791183d452923ff7/lib/client/escape/reader.go#L26-L62","documentation":"ErrTooMuchBufferedData is returned by escape.Reader when its internal buffer exceeds 10MB because the consumer is not reading fast enough or is entirely stuck. It doubles as a stuck-session watchdog: setErr tears down the reader so an unresponsive downstream cannot buffer unboundedly.","triggerScenarios":"reader.go:177 — runReads accumulated more than 10MB in the internal buffer while waiting for the consumer to Read; the reader unlocks, sets the error, and stops. Typically means the session output consumer stopped consuming (dead process, blocked pipe).","commonSituations":"A hung remote command producing output while the local terminal writer is blocked; a consumer goroutine that exited without closing the session; extremely bursty output exceeding 10MB faster than the terminal renders.","solutions":["Ensure the Reader's consumer continuously drains it (do not block the read loop on slow UI/terminal writes).","Treat errors.Is(err, escape.ErrTooMuchBufferedData) as a stuck-session condition and terminate the session.","Investigate why the consumer stalled — check the writer side (terminal, logger, pipe) for blocking.","If data volume is legitimately high, consume faster or use a backpressure-aware design instead of buffering."],"exampleFix":"// before\n_, err := io.Copy(out, r)\nrequire.Equal(t, err, ErrTooMuchBufferedData) // consumer stalled until 10MB filled\n// after\n// keep the consumer draining concurrently so the buffer never overflows\ngo func() { _, _ = io.Copy(out, r) }()","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func IsBufferOverflow(err error) bool { return errors.Is(err, escape.ErrTooMuchBufferedData) }","tryCatchPattern":"_, err := io.Copy(out, r)\nif errors.Is(err, escape.ErrTooMuchBufferedData) {\n    log.Warn(\"session consumer stalled; terminating stuck session\")\n    return errStuckSession\n}","preventionTips":["Keep the reader's consumer draining continuously (never block the read loop on slow writers)","Monitor for consumer goroutine exits that leave the reader unconsumed","Treat this error as a stuck-session watchdog and terminate the session on it"],"tags":["buffer-overflow","backpressure","interactive-session","sentinel-error"],"backgroundTag":"buffer-overflow","analyzedSha":"1283425b60ec5f60d509ba4c791183d452923ff7","analyzedAt":"2026-09-02T04:06:41.601Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}