txthinking/brook · warning
no question
Error message
no question
What it means
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.
Source
Thrown at relayoverbrook.go:165
if err != nil {
return err
}
defer rc.Close()
defer sc.Clean()
if err := sc.Exchange(c); err != nil {
return nil
}
return nil
}
func (s *RelayOverBrook) 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
}
}
conn, 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 conn == nil {
return nil
}View on GitHub (pinned to 5cd13ef3b1)
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).
Example fix
// before
probe := &dns.Msg{} // QD = 0
relayConn.Write(probe.Pack()) // "no question"
// after
q := new(dns.Msg)
q.SetQuestion("example.com.", dns.TypeA)
relayConn.Write(q.Pack()) Defensive patterns
Strategy: validation
Validate before calling
m := &dns.Msg{}
if err := m.Unpack(payload); err != nil || len(m.Question) == 0 {
// do not send through the DNS-mode brook relay
} Try / catch
if err := relayOverBrook.UDPHandle(s, addr, d); err != nil && err.Error() == "no question" {
// reroute via raw UDP or drop with logging
} Prevention
- 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.
When it happens
Trigger: Brook-over-relay UDP path (UDPHandle) with s.IsDNS set, receiving a datagram that unpacks to a dns.Msg with len(m.Question) == 0.
Common situations: 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.
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/c63b43e03d0d4aab.
Report an issue: GitHub.