{"record":{"id":"4c5e4cc700e0db39","repo":"grpc/grpc-go","slug":"received-d-bytes-data-exceeding-the-limit-d-byte","errorCode":null,"errorMessage":"received %d-bytes data exceeding the limit %d bytes","messagePattern":"received (.+?)-bytes data exceeding the limit (.+?) bytes","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/transport/flowcontrol.go","lineNumber":182,"sourceCode":"\t\t\t// estUntransmittedData and estSenderQuota. This will be helpful in case the message\n\t\t\t// is padded; We will fallback on the current available window(at least a 1/4th of the limit).\n\t\t\tf.delta = n\n\t\t}\n\t\treturn f.delta\n\t}\n\treturn 0\n}\n\n// onData is invoked when some data frame is received. It updates pendingData.\nfunc (f *inFlow) onData(n uint32) error {\n\tf.mu.Lock()\n\tdefer f.mu.Unlock()\n\n\tf.pendingData += n\n\tif f.pendingData+f.pendingUpdate > f.limit+f.delta {\n\t\tlimit := f.limit\n\t\trcvd := f.pendingData + f.pendingUpdate\n\t\treturn fmt.Errorf(\"received %d-bytes data exceeding the limit %d bytes\", rcvd, limit)\n\t}\n\treturn nil\n}\n\n// onRead is invoked when the application reads the data. It returns the window size\n// to be sent to the peer.\nfunc (f *inFlow) onRead(n uint32) uint32 {\n\tf.mu.Lock()\n\tdefer f.mu.Unlock()\n\n\tif f.pendingData == 0 {\n\t\treturn 0\n\t}\n\tf.pendingData -= n\n\tif n > f.delta {\n\t\tn -= f.delta\n\t\tf.delta = 0\n\t} else {","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/transport/flowcontrol.go#L164-L200","documentation":"Fires in inFlow.onData (flowcontrol.go:182) when received-but-unconsumed data plus pending window updates exceed the flow-control window (limit + delta). This is the receiver-side enforcement of HTTP/2 flow control: the peer sent more DATA bytes than the advertised window allowed, which is a protocol violation by the peer, so the connection/stream must error out.","triggerScenarios":"A remote peer (client or server) sends DATA frames whose cumulative bytes exceed the window gRPC advertised. Caused by a buggy/non-conformant HTTP/2 stack on the peer, a corrupted window-update sequence, or a peer that ignores WINDOW_UPDATE/RST_STREAM accounting. The exact numbers are reported: received bytes vs the window limit.","commonSituations":"Interop with a broken HTTP/2 implementation; a proxy or load balancer that mishandles flow control; streaming very large messages where a race or bug causes the peer to overrun; memory pressure where the receiver shrinks the window but the peer doesn't honor it.","solutions":["Capture the error's reported limit and received bytes; if received is only slightly over, suspect a race or a peer accounting bug.","Update the peer's HTTP/2/gRPC stack to a conformant version, or replace a misbehaving intermediary (proxy/LB).","If you control the receiver, ensure the application drains streams promptly so window updates are sent (slow readers can compound flow-control stress, though this specific error indicates a real overrun, not just backpressure).","File/inspect channelz metrics for the connection to confirm which peer stream triggered the overrun."],"exampleFix":"// This is a peer-side protocol violation; no local code change 'fixes' it.\n// Mitigate by handling the RPC error and upgrading/replacing the peer.\n\nstream, _ := client.SomeMethod(ctx)\nfor {\n    if _, err := stream.Recv(); err != nil {\n        if status.Code(err) == codes.ResourceExhausted || isFlowControl(err) {\n            log.Printf(\"peer overran flow control; reconnecting: %v\", err)\n            // back off, reconnect, or report upstream\n        }\n        break\n    }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if _, err := stream.Recv(); err != nil {\n    // flow-control overrun surfaces as a transport/RPC error;\n    // check status and reconnect or report the peer.\n    st, _ := status.FromError(err)\n    log.Printf(\"stream error (possible flow-control overrun): code=%s msg=%s\", st.Code(), st.Message())\n}","preventionTips":["Upgrade/replace peers or intermediaries that violate HTTP/2 flow control.","Drain streams promptly so window updates flow back to the sender.","Monitor channelz for per-connection flow-control errors."],"tags":["flow-control","http2","transport","protocol-violation","peer"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}