txthinking/brook · warning
no question
Error message
no question
What it means
When the relay is in DNS mode (IsDNS), UDPHandle unpacks the incoming UDP payload as a DNS message and requires at least one Question entry. A DNS message with zero questions cannot be routed by DNSGate, so the relay rejects it with "no question" instead of forwarding it.
Source
Thrown at relay.go:170
i, err := c.Read(bf[:])
if err != nil {
return nil
}
if _, err := rc.Write(bf[0:i]); err != nil {
return nil
}
}
return nil
}
func (s *Relay) UDPHandle(addr *net.UDPAddr, b []byte, l1 *net.UDPConn) error {
if s.IsDNS {
m := &dns.Msg{}
if err := m.Unpack(b); err != nil {
return err
}
if len(m.Question) == 0 {
return errors.New("no question")
}
done, err := DNSGate(addr, m, l1)
if err != nil {
return err
}
if done {
return nil
}
}
c, err := s.Pcf.Handle(addr, s.Dstb, b, func(b []byte) (int, error) {
return l1.WriteToUDP(b, addr)
}, s.UDPTimeout)
if err != nil {
return err
}
if c == nil {
return nil
}View on GitHub (pinned to 5cd13ef3b1)
Solutions
- Ensure only real DNS queries (with a QD section) are sent to the DNS-mode relay port.
- If you need to transport non-query DNS messages, disable IsDNS mode on the relay so packets are forwarded raw without DNS validation.
- Inspect the offending client packet; if it's a health check, switch it to a proper query like a type-A lookup for a probe domain.
Example fix
// before
conn.Write(buildDNSMsgWithNoQuestion()) // relay replies: no question
// after
m := buildDNSMsg()
m.SetQuestion(dns.Fqdn("probe.example.com"), dns.TypeA) // QD=1, relay accepts Defensive patterns
Strategy: validation
Validate before calling
func isRoutableDNSQuery(b []byte) bool {
m := &dns.Msg{}
if m.Unpack(b) != nil {
return false
}
return len(m.Question) > 0
} Try / catch
if err := relay.UDPHandle(s, addr, d); err != nil && err.Error() == "no question" {
log.Printf("dropping non-query DNS datagram from %s", addr)
} Prevention
- Only point genuine DNS resolvers/clients at a relay with IsDNS enabled.
- Send health-check traffic as real queries (e.g. type-A for a probe domain).
- Turn off IsDNS if you must forward arbitrary UDP payloads.
When it happens
Trigger: Relay.UDPHandle receives a UDP packet whose bytes unpack into a valid dns.Msg but with len(m.Question) == 0 — e.g. non-query DNS traffic (NOTIFY without question in some encodings, empty EDNS keepalive probes) or a payload that happens to parse as a header-only DNS message.
Common situations: Misconfigured clients pointing arbitrary UDP traffic at a DNS-mode relay port; malformed or minimal DNS probes; tools sending zero-question DNS datagrams for liveness checks.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- no question
- This is ipv4
- invalid type
- socks5 server requires a clear IP for UDP, only port is not
- Invalid prefer
AI-assisted analysis of txthinking/brook@5cd13ef3b1 (2026-09-06).
Data as JSON: /api/errors/e8fc88207622da69.
Report an issue: GitHub.