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

  1. Send only well-formed DNS queries (one or more questions) through the DNS-mode relay.
  2. Disable IsDNS on the relay if raw/non-query UDP forwarding is required.
  3. 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

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


AI-assisted analysis of txthinking/brook@5cd13ef3b1 (2026-09-06). Data as JSON: /api/errors/c63b43e03d0d4aab. Report an issue: GitHub.