cloudflare/cloudflared · warning
error setting read deadline: %w
Error message
error setting read deadline: %w
What it means
GorillaConn.SetDeadline implements net.Conn by delegating to the underlying gorilla websocket connection. This error wraps a failure from SetReadDeadline, which happens when the underlying connection's deadline setter reports the connection is already closed or in an unusable state.
Source
Thrown at websocket/connection.go:73
return copied, nil
}
// Write will write messages to the websocket connection
func (c *GorillaConn) Write(p []byte) (int, error) {
if err := c.Conn.WriteMessage(websocket.BinaryMessage, p); err != nil {
return 0, err
}
return len(p), nil
}
// SetDeadline sets both read and write deadlines, as per net.Conn interface docs:
// "It is equivalent to calling both SetReadDeadline and SetWriteDeadline."
// Note there is no synchronization here, but the gorilla implementation isn't thread safe anyway
func (c *GorillaConn) SetDeadline(t time.Time) error {
if err := c.Conn.SetReadDeadline(t); err != nil {
return fmt.Errorf("error setting read deadline: %w", err)
}
if err := c.Conn.SetWriteDeadline(t); err != nil {
return fmt.Errorf("error setting write deadline: %w", err)
}
return nil
}
type Conn struct {
rw io.ReadWriter
log *zerolog.Logger
// writeLock makes sure
// 1. Only one write at a time. The pinger and Stream function can both call write.
// 2. Close only returns after in progress Write is finished, and no more Write will succeed after calling Close.
writeLock sync.Mutex
done bool
}
func NewConn(ctx context.Context, rw io.ReadWriter, log *zerolog.Logger) *Conn {View on GitHub (pinned to 2253eeeb25)
Solutions
- Check whether the connection was already closed — stop deadline timers on connection shutdown
- Ignore/treat as benign errors of type net.ErrClosed or use-after-close in deadline reset paths
- Ensure Close() cancels the goroutines/timers that call SetDeadline before closing
- If gorilla returns 'use of closed network connection', rebuild the connection rather than retrying the deadline
Example fix
// before
if err := conn.SetDeadline(time.Now().Add(pongWait)); err != nil {
return err // aborts even during shutdown
}
// after
if err := conn.SetDeadline(time.Now().Add(pongWait)); err != nil {
if errors.Is(err, net.ErrClosed) {
return nil // connection is shutting down
}
return fmt.Errorf("set deadline: %w", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
func canSetDeadline(c net.Conn) bool {
return c.SetDeadline(time.Now()) == nil || !errors.Is(c.SetDeadline(time.Now()), net.ErrClosed)
} Try / catch
if err := conn.SetDeadline(t); err != nil {
if errors.Is(err, net.ErrClosed) || strings.Contains(err.Error(), "use of closed") {
return nil // expected during shutdown
}
return err
} Prevention
- Cancel deadline-refresh timers before closing the connection
- Use sync/onClose hooks so no goroutine touches a closed conn
- Distinguish shutdown-time errors from real failures
When it happens
Trigger: Calling SetDeadline (directly or via net.Conn plumbing like conn.SetDeadline in proxy/ssh/rdp over websocket code) after the websocket has been closed or the underlying TCP conn has errored.
Common situations: Deadline refresh timers racing connection shutdown; one side closed the tunnel while keepalive/ping loops still reset deadlines; use-after-close in proxy streams.
Related errors
- error setting write deadline: %w
- internal error: unsupported connection type
- Failed to fetch resource
- write to closed websocket connection
- status not yet written before attempting to hijack connectio
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/71e96bb0528360b4.
Report an issue: GitHub.