{"record":{"id":"c63b43e03d0d4aab","repo":"txthinking/brook","slug":"no-question-c63b43","errorCode":null,"errorMessage":"no question","messagePattern":"no question","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"relayoverbrook.go","lineNumber":165,"sourceCode":"\tif err != nil {\n\t\treturn err\n\t}\n\tdefer rc.Close()\n\tdefer sc.Clean()\n\tif err := sc.Exchange(c); err != nil {\n\t\treturn nil\n\t}\n\treturn nil\n}\n\nfunc (s *RelayOverBrook) UDPHandle(addr *net.UDPAddr, b []byte, l1 *net.UDPConn) error {\n\tif s.IsDNS {\n\t\tm := &dns.Msg{}\n\t\tif err := m.Unpack(b); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif len(m.Question) == 0 {\n\t\t\treturn errors.New(\"no question\")\n\t\t}\n\t\tdone, err := DNSGate(addr, m, l1)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif done {\n\t\t\treturn nil\n\t\t}\n\t}\n\tconn, err := s.pcf.Handle(addr, s.dstb, b, func(b []byte) (int, error) {\n\t\treturn l1.WriteToUDP(b, addr)\n\t}, s.UDPTimeout)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif conn == nil {\n\t\treturn nil\n\t}","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/txthinking/brook/blob/5cd13ef3b1fb574e88ebf2c1b5d95f2ebe1342c8/relayoverbrook.go#L147-L183","documentation":"relayoverbrook.go's UDPHandle contains the same DNS-mode guard as relay.go: in IsDNS mode it unpacks the payload with miekg/dns and rejects messages with an empty Question section, since DNSGate routing depends on the question name/type.","triggerScenarios":"Brook-over-relay UDP path (UDPHandle) with s.IsDNS set, receiving a datagram that unpacks to a dns.Msg with len(m.Question) == 0.","commonSituations":"Same as relay.go:77 — zero-question DNS datagrams (keepalives, malformed probes) or non-DNS UDP traffic pointed at a DNS-mode relay; duplicate guard exists because relayoverbrook mirrors the relay UDP handler.","solutions":["Send only well-formed DNS queries (one or more questions) through the DNS-mode relay.","Disable IsDNS on the relay if raw/non-query UDP forwarding is required.","Fix the client tool producing questionless DNS datagrams (often a health-check or buggy DNS stub)."],"exampleFix":"// before\nprobe := &dns.Msg{} // QD = 0\nrelayConn.Write(probe.Pack()) // \"no question\"\n\n// after\nq := new(dns.Msg)\nq.SetQuestion(\"example.com.\", dns.TypeA)\nrelayConn.Write(q.Pack())","handlingStrategy":"validation","validationCode":"m := &dns.Msg{}\nif err := m.Unpack(payload); err != nil || len(m.Question) == 0 {\n    // do not send through the DNS-mode brook relay\n}","typeGuard":null,"tryCatchPattern":"if err := relayOverBrook.UDPHandle(s, addr, d); err != nil && err.Error() == \"no question\" {\n    // reroute via raw UDP or drop with logging\n}","preventionTips":["Validate QD>=1 client-side before writing to a DNS-mode relay.","Keep health probes as normal DNS queries.","Disable IsDNS for non-DNS UDP workloads."],"tags":["network","dns","udp","validation"],"backgroundTag":"empty-required-field","analyzedSha":"5cd13ef3b1fb574e88ebf2c1b5d95f2ebe1342c8","analyzedAt":"2026-09-06T04:35:00.432Z","contentChangedAt":"2026-09-06T04:35:00.432Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}