{"record":{"id":"9cf374cdedcf0bcf","repo":"ginuerzh/gost","slug":"read-not-supported-9cf374","errorCode":null,"errorMessage":"read not supported","messagePattern":"read not supported","errorType":"error_code","errorClass":"net.OpError","httpStatus":null,"severity":"error","filePath":"http2.go","lineNumber":890,"sourceCode":"}\n\nfunc (c *http2Conn) SetReadDeadline(t time.Time) error {\n\treturn &net.OpError{Op: \"set\", Net: \"http2\", Source: nil, Addr: nil, Err: errors.New(\"deadline not supported\")}\n}\n\nfunc (c *http2Conn) SetWriteDeadline(t time.Time) error {\n\treturn &net.OpError{Op: \"set\", Net: \"http2\", Source: nil, Addr: nil, Err: errors.New(\"deadline not supported\")}\n}\n\n// a dummy HTTP2 server conn used by HTTP2 handler\ntype http2ServerConn struct {\n\tr      *http.Request\n\tw      http.ResponseWriter\n\tclosed chan struct{}\n}\n\nfunc (c *http2ServerConn) Read(b []byte) (n int, err error) {\n\treturn 0, &net.OpError{Op: \"read\", Net: \"http2\", Source: nil, Addr: nil, Err: errors.New(\"read not supported\")}\n}\n\nfunc (c *http2ServerConn) Write(b []byte) (n int, err error) {\n\treturn 0, &net.OpError{Op: \"write\", Net: \"http2\", Source: nil, Addr: nil, Err: errors.New(\"write not supported\")}\n}\n\nfunc (c *http2ServerConn) Close() error {\n\tselect {\n\tcase <-c.closed:\n\tdefault:\n\t\tclose(c.closed)\n\t}\n\treturn nil\n}\n\nfunc (c *http2ServerConn) LocalAddr() net.Addr {\n\taddr, _ := net.ResolveTCPAddr(\"tcp\", c.r.Host)\n\treturn addr","sourceCodeStart":872,"sourceCodeEnd":908,"githubUrl":"https://github.com/ginuerzh/gost/blob/a33fdbf4c98034f4bfeeaea9868909822b9c526d/http2.go#L872-L908","documentation":"http2ServerConn wraps only the server side of an HTTP request/response (http.Request + http.ResponseWriter). Reading raw bytes is meaningless in that model, so Read always returns 0 bytes and a *net.OpError with \"read not supported\".","triggerScenarios":"Calling Read() on an http2ServerConn obtained from the HTTP/2 handler path, e.g. passing the conn to code expecting a bidirectional net.Conn (relay, io.Copy from the conn).","commonSituations":"Using the handler-side dummy conn in a tunneling relay where the developer expected a full-duplex conn; mixing up http2ServerConn (handler side) with http2Conn (dialer/listener side, which supports Read).","solutions":["Read the request body via c.r.Body (the wrapped *http.Request) instead of conn.Read.","Use http2Conn (from the h2 listener Accept path) when a bidirectional net.Conn is required.","Refactor code that io.Copy's from the conn to consume r.Body and write to w explicitly.","Guard with a type check so the dummy server conn is never fed to conn-oriented APIs."],"exampleFix":"// before\nio.Copy(dst, serverConn) // read not supported\n// after\nio.Copy(dst, serverConn.r.Body) // read the HTTP request body","handlingStrategy":"type-guard","validationCode":"// before relaying, ensure the conn supports reading\nfunc readable(c net.Conn) bool {\n    _, isDummy := c.(interface{ IsServerDummy() bool })\n    return !isDummy // http2ServerConn cannot Read\n}","typeGuard":"func isH2ServerConn(c net.Conn) bool {\n    // http2ServerConn exposes RemoteAddr resolved from the HTTP request\n    _, ok := c.(interface{ Read([]byte) (int, error) })\n    _ = ok\n    // prefer explicit type assertion in-package:\n    _, isDummy := c.(*gosthttp2.ServerConnLike)\n    return !isDummy\n}","tryCatchPattern":"n, err := conn.Read(buf)\nif err != nil {\n    var oe *net.OpError\n    if errors.As(err, &oe) && strings.Contains(err.Error(), \"read not supported\") {\n        return fmt.Errorf(\"use r.Body for handler-side http2 conns\")\n    }\n    return err\n}","preventionTips":["Never feed http2ServerConn to io.Copy/relay code expecting a bidirectional conn.","Read request data from c.r.Body and write responses via c.w.","Use h2Conn from the listener Accept path when a real net.Conn is needed."],"tags":["http2","read","unsupported-operation","net-conn"],"backgroundTag":"operation-not-supported","analyzedSha":"a33fdbf4c98034f4bfeeaea9868909822b9c526d","analyzedAt":"2026-09-02T22:15:54.506Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}