{"record":{"id":"77b161809abeaf64","repo":"grpc/grpc-go","slug":"received-an-illegal-stream-id-v-headers-frame","errorCode":null,"errorMessage":"received an illegal stream id: %v. headers frame: %+v","messagePattern":"received an illegal stream id: (.+?)\\. headers frame: %\\+v","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"internal/transport/http2_server.go","lineNumber":398,"sourceCode":"\tdefer t.maxStreamMu.Unlock()\n\n\tstreamID := frame.Header().StreamID\n\n\t// frame.Truncated is set to true when framer detects that the current header\n\t// list size hits MaxHeaderListSize limit.\n\tif frame.Truncated {\n\t\tt.controlBuf.put(&cleanupStream{\n\t\t\tstreamID: streamID,\n\t\t\trst:      true,\n\t\t\trstCode:  http2.ErrCodeFrameSize,\n\t\t\tonWrite:  func() {},\n\t\t})\n\t\treturn nil\n\t}\n\n\tif streamID%2 != 1 || streamID <= t.maxStreamID {\n\t\t// illegal gRPC stream id.\n\t\treturn fmt.Errorf(\"received an illegal stream id: %v. headers frame: %+v\", streamID, frame)\n\t}\n\tt.maxStreamID = streamID\n\n\ts := &ServerStream{\n\t\tStream: Stream{\n\t\t\tid: streamID,\n\t\t\tfc: inFlow{limit: uint32(t.initialWindowSize)},\n\t\t},\n\t\tst:               t,\n\t\theaderWireLength: int(frame.Header().Length),\n\t}\n\ts.Stream.buf.init()\n\tvar (\n\t\t// if false, content-type was missing or invalid\n\t\tisGRPC      = false\n\t\tcontentType = \"\"\n\t\tmdata       = make(metadata.MD, len(frame.Fields))\n\t\thttpMethod  string","sourceCodeStart":380,"sourceCodeEnd":416,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/internal/transport/http2_server.go#L380-L416","documentation":"This error occurs in operateHeaders when an incoming HEADERS frame has a stream ID that is either even (client-initiated streams must use odd IDs per HTTP/2 spec) or less than or equal to the maximum stream ID already seen (streams must be monotonically increasing). This is treated as a protocol violation and triggers a GOAWAY with PROTOCOL_ERROR.","triggerScenarios":"A client sends a HEADERS frame with an even stream ID, or reuses/collides with a stream ID lower than a previously established stream. The server detects the violation in operateHeaders and returns the error which causes a connection-level GOAWAY.","commonSituations":"Buggy or non-compliant HTTP/2 client library that generates incorrect stream IDs, a client implementing HTTP/2 multiplexing incorrectly, connection hijacking/probing by a non-gRPC client, or a badly behaving intermediary/proxy that reuses stream IDs.","solutions":["Identify the client library/implementation generating invalid stream IDs — this is a client-side protocol bug.","Upgrade the client's HTTP/2 or gRPC library to a compliant version.","If behind a proxy/L7 load balancer, verify it correctly forwards HTTP/2 stream IDs.","Check for concurrent connections being multiplexed incorrectly by an intermediary."],"exampleFix":"// No client-side code fix — this is a protocol-level violation by the peer.\n// Ensure the client uses a compliant gRPC/HTTP2 library:\n\n// before (broken): custom/raw HTTP2 client with bad stream ID management\n// (even or reused stream IDs)\n\n// after (valid): use grpc-go or another compliant gRPC client library\nconn, err := grpc.Dial(target, grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)))","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":"// This error causes a GOAWAY — the connection is terminated.\n// On the client side, handle connection-level errors with reconnection:\nif status.Code(err) == codes.Unavailable {\n    if strings.Contains(err.Error(), \"GOAWAY\") || strings.Contains(err.Error(), \"protocol\") {\n        // gRPC client will automatically reconnect via the name resolver\n        log.Printf(\"connection terminated due to protocol violation\")\n    }\n}","preventionTips":["Use compliant gRPC client libraries to avoid generating invalid stream IDs.","Avoid custom/raw HTTP/2 implementations for gRPC traffic.","Monitor server logs for GOAWAY/protocol errors to identify problematic clients.","Keep client gRPC library versions up to date."],"tags":["transport","http2","stream","protocol-violation","network"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}