ginuerzh/gost · warning
empty question
Error message
empty question
What it means
Exchange unpacks a raw DNS query and requires at least one question section to know what to resolve. A well-formed but questionless DNS message (or one whose questions were lost in an upstream transform) cannot be answered, so the error is returned.
Source
Thrown at resolver.go:389
e.SourceNetmask = 32
e.Address = ip.To4()
} else {
e.Family = 2
e.SourceNetmask = 128
e.Address = r.srcIP
}
opt.Option = append(opt.Option, e)
m.Extra = append(m.Extra, opt)
}
func (r *resolver) Exchange(ctx context.Context, query []byte) (reply []byte, err error) {
mq := &dns.Msg{}
if err = mq.Unpack(query); err != nil {
return
}
if len(mq.Question) == 0 {
return nil, errors.New("empty question")
}
var mr *dns.Msg
// Only cache for single question.
if len(mq.Question) == 1 {
key := newResolverCacheKey(&mq.Question[0])
mr = r.cache.loadCache(key)
if mr != nil {
log.Logf("[dns] exchange message %d (cached): %s", mq.Id, mq.Question[0].String())
mr.Id = mq.Id
return mr.Pack()
}
defer func() {
if mr != nil {
r.cache.storeCache(key, mr, r.TTL())
}
}()View on GitHub (pinned to a33fdbf4c9)
Solutions
- Drop the packet and reply with FORMERR (or nothing) instead of retrying
- Fix the client/handler that produces DNS messages without a Question section
- Validate incoming DNS messages at the ingress before calling Exchange
Example fix
// before
resp, err := resolver.Exchange(query)
// after
mq := &dns.Msg{}
if err := mq.Unpack(query); err != nil || len(mq.Question) == 0 {
return dns.Msg{}
}
resp, err := resolver.Exchange(query) Defensive patterns
Strategy: validation
Validate before calling
mq := &dns.Msg{}
if err := mq.Unpack(query); err != nil {
return err
}
if len(mq.Question) == 0 {
return errors.New("refusing to resolve message with no question")
} Try / catch
resp, err := resolver.Exchange(query)
if err != nil {
return newFormErrorResponse(query) // respond FORMERR, don't retry
} Prevention
- Validate DNS messages before forwarding them upstream
- Reply FORMERR to question-less queries
- Log sources of malformed queries to identify buggy clients
When it happens
Trigger: Calling Exchange with a query that Unpacks successfully but has len(mq.Question) == 0 — e.g. an empty QUERY opcode packet or a malformed client request.
Common situations: Buggy or hostile DNS clients sending question-less messages; port-scan probes on the DNS port; a handler stripping the question before forwarding.
Related errors
- resolver: domain %s does not exists
- connection queue is full
- connection is closed
- broken pipe
- deadline not supported
AI-assisted analysis of ginuerzh/gost@a33fdbf4c9 (2026-09-02).
Data as JSON: /api/errors/e8a279b6c1a35288.
Report an issue: GitHub.