{"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":"error","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/0c51461d27177d997e14c642fe18c11668fc09a3/internal/transport/http2_server.go#L380-L416","documentation":"Fires in http2Server.operateHeaders (http2_server.go:398) when an incoming HEADERS frame carries a stream ID that is even (server-initiated IDs are reserved) or not strictly greater than the maximum stream ID already seen on this connection. HTTP/2 requires client-initiated stream IDs to be odd and monotonically increasing, so this is a protocol violation by the client.","triggerScenarios":"A client sends a HEADERS frame with streamID%2==0 (even) or streamID <= t.maxStreamID (reused/decreasing). Produced by a non-conformant HTTP/2 client stack, a buggy gRPC client, or an intermediary that rewrites frames incorrectly. The error message dumps both the bad ID and the full headers frame for diagnosis.","commonSituations":"Interop with a broken client or proxy that generates stream IDs incorrectly; a client library bug after a reconnect that resets stream-ID accounting; fuzzing or malformed traffic; a middlebox that multiplexes streams from several clients onto one connection with clashing IDs.","solutions":["Identify the offending client from the logged headers frame and upgrade/replace its HTTP/2 or gRPC stack.","If a middlebox (proxy/LB/sidecar) is in the path, verify it preserves HTTP/2 stream-ID semantics or bypass it to confirm.","There is no server-side configuration to 'accept' illegal IDs; the connection must be closed per spec, so the fix is on the sender side.","Ensure your client uses a supported grpc.ClientConn and reuses connections correctly rather than hand-crafting frames."],"exampleFix":"// Server-side: nothing to change; this is a client protocol violation.\n// On the client, ensure you use grpc.Dial/grpc.NewClient and a current\n// gRPC version that emits valid stream IDs.\n\nconn, err := grpc.NewClient(target, grpc.WithTransportCredentials(creds))\n// avoid hand-rolled HTTP/2 framing; let gRPC manage stream IDs.","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Server-side: the connection is closed automatically; handle RPC failures.\nif err := srvStream.SendMsg(resp); err != nil {\n    log.Printf(\"client connection dropped (possible protocol violation): %v\", err)\n}","preventionTips":["Use supported gRPC clients; avoid hand-rolled HTTP/2 framing.","Ensure middleboxes preserve stream-ID semantics.","Keep client gRPC versions current."],"tags":["http2","transport","protocol-violation","server","stream-id","peer"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}