{"record":{"id":"71e96bb0528360b4","repo":"cloudflare/cloudflared","slug":"error-setting-read-deadline-w","errorCode":null,"errorMessage":"error setting read deadline: %w","messagePattern":"error setting read deadline: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"websocket/connection.go","lineNumber":73,"sourceCode":"\n\treturn copied, nil\n}\n\n// Write will write messages to the websocket connection\nfunc (c *GorillaConn) Write(p []byte) (int, error) {\n\tif err := c.Conn.WriteMessage(websocket.BinaryMessage, p); err != nil {\n\t\treturn 0, err\n\t}\n\n\treturn len(p), nil\n}\n\n// SetDeadline sets both read and write deadlines, as per net.Conn interface docs:\n// \"It is equivalent to calling both SetReadDeadline and SetWriteDeadline.\"\n// Note there is no synchronization here, but the gorilla implementation isn't thread safe anyway\nfunc (c *GorillaConn) SetDeadline(t time.Time) error {\n\tif err := c.Conn.SetReadDeadline(t); err != nil {\n\t\treturn fmt.Errorf(\"error setting read deadline: %w\", err)\n\t}\n\tif err := c.Conn.SetWriteDeadline(t); err != nil {\n\t\treturn fmt.Errorf(\"error setting write deadline: %w\", err)\n\t}\n\treturn nil\n}\n\ntype Conn struct {\n\trw  io.ReadWriter\n\tlog *zerolog.Logger\n\t// writeLock makes sure\n\t// 1. Only one write at a time. The pinger and Stream function can both call write.\n\t// 2. Close only returns after in progress Write is finished, and no more Write will succeed after calling Close.\n\twriteLock sync.Mutex\n\tdone      bool\n}\n\nfunc NewConn(ctx context.Context, rw io.ReadWriter, log *zerolog.Logger) *Conn {","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/websocket/connection.go#L55-L91","documentation":"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.","triggerScenarios":"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.","commonSituations":"Deadline refresh timers racing connection shutdown; one side closed the tunnel while keepalive/ping loops still reset deadlines; use-after-close in proxy streams.","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"],"exampleFix":"// before\nif err := conn.SetDeadline(time.Now().Add(pongWait)); err != nil {\n    return err // aborts even during shutdown\n}\n// after\nif err := conn.SetDeadline(time.Now().Add(pongWait)); err != nil {\n    if errors.Is(err, net.ErrClosed) {\n        return nil // connection is shutting down\n    }\n    return fmt.Errorf(\"set deadline: %w\", err)\n}","handlingStrategy":"try-catch","validationCode":"func canSetDeadline(c net.Conn) bool {\n    return c.SetDeadline(time.Now()) == nil || !errors.Is(c.SetDeadline(time.Now()), net.ErrClosed)\n}","typeGuard":null,"tryCatchPattern":"if err := conn.SetDeadline(t); err != nil {\n    if errors.Is(err, net.ErrClosed) || strings.Contains(err.Error(), \"use of closed\") {\n        return nil // expected during shutdown\n    }\n    return err\n}","preventionTips":["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"],"tags":["websocket","deadline","connection-lifecycle","timeout"],"backgroundTag":"connection-closed","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}