ginuerzh/gost · info · net.OpError
deadline not supported
Error message
deadline not supported
What it means
dnsServerConn.SetDeadline unconditionally returns a *net.OpError wrapping 'deadline not supported' because DNS-over-HTTP/UDP virtual connections have no real socket deadlines to enforce. This is a deliberate capability limitation of the emulated conn, satisfying the net.Conn interface without implementing deadlines.
Source
Thrown at dns.go:391
func (c *dnsServerConn) Close() error {
select {
case <-c.cclose:
default:
close(c.cclose)
}
return nil
}
func (c *dnsServerConn) LocalAddr() net.Addr {
return c.laddr
}
func (c *dnsServerConn) RemoteAddr() net.Addr {
return c.raddr
}
func (c *dnsServerConn) SetDeadline(t time.Time) error {
return &net.OpError{Op: "set", Net: "dns", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}
func (c *dnsServerConn) SetReadDeadline(t time.Time) error {
return &net.OpError{Op: "set", Net: "dns", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}
func (c *dnsServerConn) SetWriteDeadline(t time.Time) error {
return &net.OpError{Op: "set", Net: "dns", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}
type dnsResponseWriter interface {
io.Writer
RemoteAddr() net.Addr
}
type dohResponseWriter struct {
raddr net.Addr
http.ResponseWriterView on GitHub (pinned to a33fdbf4c9)
Solutions
- Skip SetDeadline calls for DNS conns or guard them behind an interface check
- Use context-based timeouts in the handler instead of conn deadlines
- Ignore the error if deadlines are non-essential for the DNS exchange
- Implement a real deadline mechanism (time.AfterFunc closing conn) if needed
Example fix
// before
conn.SetDeadline(time.Now().Add(10 * time.Second))
// after
type deadliner interface{ SetDeadline(time.Time) error }
if d, ok := conn.(deadliner); ok {
if err := d.SetDeadline(time.Now().Add(10 * time.Second)); err != nil {
log.Logf("deadline unsupported: %s", err) // DNS conn: use context timeout instead
}
} Defensive patterns
Strategy: type-guard
Validate before calling
// detect deadline support before relying on it
type deadliner interface{ SetDeadline(time.Time) error }
_, supportsDeadline := conn.(interface{ SupportsDeadline() bool }) // DNS conns do not Type guard
var _ net.Conn = (*dnsServerConn)(nil) // known: deadlines unsupported
func deadlinesSupported(c net.Conn) bool {
_, isDNSConn := c.(interface{ isDNSServerConnMarker() })
return !isDNSConn
} Try / catch
if err := conn.SetDeadline(time.Now().Add(d)); err != nil {
var opErr *net.OpError
if errors.As(err, &opErr) && opErr.Err.Error() == "deadline not supported" {
// fall back to context-based timeout
return nil
}
return err
} Prevention
- Prefer context.Context timeouts over conn deadlines for DNS-backed conns
- Wrap deadline setting in a capability check so TCP/UDP conns keep deadlines
- Document that DNS virtual conns do not support deadlines in handler code
- Ignore (don't fail on) the OpError wrapping 'deadline not supported'
When it happens
Trigger: Calling SetDeadline(t) on a conn obtained from the DNS listener's Accept(); any non-zero-time call immediately fails with this wrapped error.
Common situations: Wrapping the DNS conn in code that sets deadlines by default (e.g., io.LimitReader with timeout helpers, TLS handshake with deadline, copy loops with timeouts).
Related errors
AI-assisted analysis of ginuerzh/gost@a33fdbf4c9 (2026-09-02).
Data as JSON: /api/errors/aa93a84a0ecb128f.
Report an issue: GitHub.