{"record":{"id":"d745d078686f6147","repo":"txthinking/brook","slug":"when-write-to-client-quic-max-datagram-size-is-11","errorCode":null,"errorMessage":"when write to client, quic max datagram size is 1197","messagePattern":"when write to client, quic max datagram size is 1197","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"quicserver.go","lineNumber":187,"sourceCode":"\t\t\t\t\t\t\tRAddr: &net.TCPAddr{\n\t\t\t\t\t\t\t\tIP:   c.RemoteAddr().(*net.UDPAddr).IP,\n\t\t\t\t\t\t\t\tPort: c.RemoteAddr().(*net.UDPAddr).Port,\n\t\t\t\t\t\t\t\tZone: c.RemoteAddr().(*net.UDPAddr).Zone,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}(c)\n\t\t\t\tif c.ConnectionState().SupportsDatagrams {\n\t\t\t\t\tgo func(c quic.Connection) {\n\t\t\t\t\t\tdefer c.CloseWithError(0, \"defer\")\n\t\t\t\t\t\tfor {\n\t\t\t\t\t\t\tb, err := c.ReceiveDatagram(context.Background())\n\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconn, dstb, err := s.UDPServerConnFactory.Handle(c.RemoteAddr().(*net.UDPAddr), b, s.Password, func(b []byte) (int, error) {\n\t\t\t\t\t\t\t\tif len(b) > 1197 {\n\t\t\t\t\t\t\t\t\terr := errors.New(\"when write to client, quic max datagram size is 1197\")\n\t\t\t\t\t\t\t\t\tLog(Error{\"from\": c.RemoteAddr().String(), \"error\": err.Error()})\n\t\t\t\t\t\t\t\t\treturn 0, err\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif err := c.SendDatagram(b); err != nil {\n\t\t\t\t\t\t\t\t\treturn 0, err\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn len(b), nil\n\t\t\t\t\t\t\t}, s.UDPTimeout)\n\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\tLog(Error{\"from\": c.RemoteAddr().String(), \"error\": err.Error()})\n\t\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif conn == nil {\n\t\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tgo func() {\n\t\t\t\t\t\t\t\tdefer conn.Close()\n\t\t\t\t\t\t\t\tvar ss Exchanger","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/txthinking/brook/blob/5cd13ef3b1fb574e88ebf2c1b5d95f2ebe1342c8/quicserver.go#L169-L205","documentation":"The QUIC server enforces the same 1197-byte ceiling when sending datagrams back to the client. Inside the write-back callback of UDPServerConnFactory.Handle, any response payload longer than 1197 bytes cannot be sent as a QUIC datagram (header + AEAD overhead would exceed the QUIC datagram limit), so the server logs and returns this error to the handler instead of sending a truncated packet.","triggerScenarios":"A remote UDP peer (e.g. a DNS server) returns a response larger than 1197 bytes; the server's write-back closure in quicserver.go receives b with len(b) > 1197 and returns the error, aborting the relayed response.","commonSituations":"Large DNS responses over UDP (big TXT records, DNSSEC-signed answers, ANY queries), or any upstream UDP service that replies with datagrams near the path MTU while the client is connected via QUIC.","solutions":["Limit the request so the response fits: for DNS, query with smaller EDNS0 buffer sizes or avoid ANY/DNSSEC-heavy queries so replies stay under 1197 bytes.","Route large UDP exchanges over TCP (DNS over TCP) or use a stream-based proxy transport instead of QUIC datagrams.","On the client, handle the failed response by retrying over a TCP-backed path when the server reports this error."],"exampleFix":"// before\nresp, _ := resolver.Exchange(bigQuery, udpViaQuic) // server rejects >1197-byte reply\n\n// after\nif resp.Len() > 1197 {\n    resp, err = resolver.ExchangeViaTCP(bigQuery) // stream path has no datagram cap\n}","handlingStrategy":"try-catch","validationCode":"// client-side guard before sending a query whose reply may be large\nif requestKind == dnsKIND_ANY || ednsBufferSize > 1232 {\n    useTCPPath = true\n}","typeGuard":null,"tryCatchPattern":"// server write-back closure returns the error to the factory handler\nif len(b) > 1197 {\n    return 0, errTooLarge // caller should retry over TCP/stream path\n}","preventionTips":["Keep EDNS advertised UDP buffer size at or below 1232 so DNS replies fit QUIC datagrams.","Avoid ANY/DNSSEC-heavy queries through QUIC-transported UDP.","Provide a TCP fallback path for clients when the server rejects oversized replies."],"tags":["network","quic","udp","datagram-size"],"backgroundTag":"payload-too-large","analyzedSha":"5cd13ef3b1fb574e88ebf2c1b5d95f2ebe1342c8","analyzedAt":"2026-09-06T04:35:00.432Z","contentChangedAt":"2026-09-06T04:35:00.432Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}