ginuerzh/gost · info · net.OpError
deadline not supported
Error message
deadline not supported
What it means
http2Conn does not support deadlines: SetDeadline always returns a *net.OpError wrapping "deadline not supported". HTTP/2 multiplexed streams in this library provide no mechanism to set an overall I/O deadline on the wrapped conn, so the net.Conn deadline API is stubbed out.
Source
Thrown at http2.go:871
if rc, ok := c.r.(io.Closer); ok {
err = rc.Close()
}
if w, ok := c.w.(io.Closer); ok {
err = w.Close()
}
return
}
func (c *http2Conn) LocalAddr() net.Addr {
return c.localAddr
}
func (c *http2Conn) RemoteAddr() net.Addr {
return c.remoteAddr
}
func (c *http2Conn) SetDeadline(t time.Time) error {
return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}
func (c *http2Conn) SetReadDeadline(t time.Time) error {
return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}
func (c *http2Conn) SetWriteDeadline(t time.Time) error {
return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}
// a dummy HTTP2 server conn used by HTTP2 handler
type http2ServerConn struct {
r *http.Request
w http.ResponseWriter
closed chan struct{}
}
func (c *http2ServerConn) Read(b []byte) (n int, err error) {View on GitHub (pinned to a33fdbf4c9)
Solutions
- Skip SetDeadline calls when the conn is an http2Conn (type-assert or feature-detect) and rely on context cancellation of the underlying HTTP/2 request instead.
- Implement read/write timeouts at the application layer using goroutines + timers around Read/Write.
- Use the h2/tls transport's context or Close() as the timeout mechanism instead of deadlines.
- Check err from SetDeadline and log-or-ignore if it is the unsupported-deadline OpError rather than treating it as fatal.
Example fix
// before
conn.SetDeadline(time.Now().Add(10 * time.Second)) // returns error
// after
if dc, ok := conn.(interface{ SetDeadline(time.Time) error }); ok {
if err := dc.SetDeadline(time.Now().Add(10 * time.Second)); err != nil {
// http2 conn: use ctx cancellation instead
ctx, cancel = context.WithTimeout(ctx, 10*time.Second)
}
} Defensive patterns
Strategy: type-guard
Validate before calling
// detect deadline support before calling
canDeadline := func(c net.Conn) bool {
type dl interface{ SetDeadline(time.Time) error }
_, ok := c.(dl)
return ok // http2Conn still implements it but always errors; prefer context timeouts
} Type guard
func supportsDeadline(c net.Conn) bool {
var opErr *net.OpError
err := c.SetDeadline(time.Now())
return !(err != nil && errors.As(err, &opErr) && opErr.Net == "http2")
} Try / catch
if err := conn.SetDeadline(t); err != nil {
var oe *net.OpError
if errors.As(err, &oe) && oe.Net == "http2" {
// fall back to context-based timeout
ctx, cancel := context.WithTimeout(ctx, d)
defer cancel()
} else {
return err
}
} Prevention
- Use context timeouts for HTTP/2 stream operations instead of conn deadlines.
- Keep timeout logic per-conn-type instead of a single generic path.
- Remember TLS wrappers call SetDeadline during handshake — supply conns that support it.
When it happens
Trigger: Calling SetDeadline(t) on a conn obtained from an http2 listener/dialer, typically via generic net.Conn timeout code (conn.SetDeadline(time.Now().Add(5*time.Second))) or code paths like tls.Server(conn) that set handshake deadlines.
Common situations: Dropping an http2Conn into middleware that uniformly sets deadlines on all net.Conn values; wrapping in TLS or proxy code that relies on SetDeadline; porting code written for TCP conns to http2 conns.
Related errors
- deadline not supported
- read not supported
- write not supported
- deadline not supported
- deadline not supported
AI-assisted analysis of ginuerzh/gost@a33fdbf4c9 (2026-09-02).
Data as JSON: /api/errors/dcae745c18e201aa.
Report an issue: GitHub.