{"record":{"id":"0ec4126e7f4edecc","repo":"ginuerzh/gost","slug":"read-from-closed-connection","errorCode":null,"errorMessage":"read from closed connection","messagePattern":"read from closed connection","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"udp.go","lineNumber":249,"sourceCode":"\t}\n\tgo c.ttlWait()\n\treturn c\n}\n\nfunc (c *udpServerConn) Read(b []byte) (n int, err error) {\n\tn, _, err = c.ReadFrom(b)\n\treturn\n}\n\nfunc (c *udpServerConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {\n\tselect {\n\tcase bb := <-c.rChan:\n\t\tn = copy(b, bb)\n\t\tif cap(bb) == mediumBufferSize {\n\t\t\tmPool.Put(bb[:cap(bb)])\n\t\t}\n\tcase <-c.closed:\n\t\terr = errors.New(\"read from closed connection\")\n\t\treturn\n\t}\n\n\tselect {\n\tcase c.nopChan <- n:\n\tdefault:\n\t}\n\n\taddr = c.raddr\n\n\treturn\n}\n\nfunc (c *udpServerConn) Write(b []byte) (n int, err error) {\n\treturn c.WriteTo(b, c.raddr)\n}\n\nfunc (c *udpServerConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {","sourceCodeStart":231,"sourceCodeEnd":267,"githubUrl":"https://github.com/ginuerzh/gost/blob/a33fdbf4c98034f4bfeeaea9868909822b9c526d/udp.go#L231-L267","documentation":"udpConn.ReadFrom returns this error when the connection's `closed` channel has been signaled, meaning ReadFrom was called on an already-closed UDP connection. Any buffered packets in rChan are discarded once closed, so subsequent reads fail with this sentinel.","triggerScenarios":"Calling Read/ReadFrom on a *udpConn after Close() has completed; a read goroutine still blocked on rChan when another goroutine closes the connection.","commonSituations":"Relay/pump goroutines not cancelled before connection close; closing the conn in a timeout handler while a reader is active; double-close cleanup paths.","solutions":["Exit the read loop when this error is returned — the connection is closed and will produce no more data.","Cancel read goroutines (context or done channel) before or atomically with closing the connection.","Treat this error as io.EOF/io.ErrClosedPipe equivalent and stop reading rather than retrying."],"exampleFix":"// before\nfor {\n    n, addr, err := conn.ReadFrom(buf)\n    if err != nil {\n        log.Println(err)\n        continue // spins on closed conn\n    }\n}\n// after\nfor {\n    n, addr, err := conn.ReadFrom(buf)\n    if err != nil {\n        return // conn closed; stop reading\n    }\n}\n","handlingStrategy":"type-guard","validationCode":"select {\ncase <-c.done:\n    return // skip reads after shutdown signaled\ndefault:\n}","typeGuard":"func isConnClosedReadErr(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"read from closed connection\")\n}","tryCatchPattern":"n, addr, err := conn.ReadFrom(buf)\nif err != nil {\n    if isConnClosedReadErr(err) { return } // expected during shutdown\n    log.Printf(\"read: %v\", err)\n}","preventionTips":["Cancel all reader goroutines before/when closing the connection.","Treat this error like io.EOF: stop reading, don't retry.","Centralize the read loop so close/read teardown is ordered once.","Use context.Done() alongside read completion to avoid races."],"tags":["udp","connection","closed-connection","read","network"],"backgroundTag":"use-of-closed-connection","analyzedSha":"a33fdbf4c98034f4bfeeaea9868909822b9c526d","analyzedAt":"2026-09-02T22:15:54.506Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}