ginuerzh/gost · error · net.OpError
read not supported
Error message
read not supported
What it means
nopConn is a do-nothing net.Conn (a sink/discarded connection); its Read always fails with a *net.OpError whose Err is 'read not supported'. The library throws this because a nop connection has no peer and no data stream — reading from it is meaningless. It exists so code that requires a net.Conn can be handed a harmless placeholder.
Source
Thrown at gost.go:159
w io.Writer
}
func (rw *readWriter) Read(p []byte) (n int, err error) {
return rw.r.Read(p)
}
func (rw *readWriter) Write(p []byte) (n int, err error) {
return rw.w.Write(p)
}
var nopClientConn = &nopConn{}
// a nop connection implements net.Conn,
// it does nothing.
type nopConn struct{}
func (c *nopConn) Read(b []byte) (n int, err error) {
return 0, &net.OpError{Op: "read", Net: "nop", Source: nil, Addr: nil, Err: errors.New("read not supported")}
}
func (c *nopConn) Write(b []byte) (n int, err error) {
return 0, &net.OpError{Op: "write", Net: "nop", Source: nil, Addr: nil, Err: errors.New("write not supported")}
}
func (c *nopConn) Close() error {
return nil
}
func (c *nopConn) LocalAddr() net.Addr {
return nil
}
func (c *nopConn) RemoteAddr() net.Addr {
return nil
}
View on GitHub (pinned to a33fdbf4c9)
Solutions
- Don't read from nopConn — it is write/discarded-traffic only; restructure so no Read is attempted
- If you need a readable placeholder, substitute a net.Pipe() connection or an empty reader wrapped appropriately
- Check the *net.OpError's Err message ('read not supported') and skip reads for nop connections
- If you own the code, implement Read to return io.EOF instead of an error if silent termination is desired
Example fix
// before
io.Copy(dst, nop) // always errors: read not supported
// after
if _, ok := conn.(*gost.NopConn); ok {
// nothing to relay from a nop connection
return nil
}
io.Copy(dst, conn) Defensive patterns
Strategy: type-guard
Validate before calling
if _, ok := conn.(*gostNopConn); ok {
// nop connection is not readable; skip the read path
return nil
} Type guard
func isNopConn(c net.Conn) bool {
return fmt.Sprintf("%T", c) == "*gost.nopConn"
} Try / catch
n, err := conn.Read(buf)
if err != nil {
var oe *net.OpError
if errors.As(err, &oe) && oe.Err.Error() == "read not supported" {
return nil // expected for nop connections
}
return err
} Prevention
- Only use nopConn where traffic is intentionally discarded
- Never pass nopConn into io.Copy or relay loops as a source
- Prefer net.Pipe() endpoints when a readable stub is needed
When it happens
Trigger: Any call to Read(b []byte) on a value of type *nopConn, e.g. when code copies/relays from a connection that was substituted with a nopConn (bypass node, discarded traffic, testing placeholder).
Common situations: io.Copy from a nopConn in a relay pair; generic code that assumes every net.Conn is readable; tests that accidentally wire the nop connection into a data path.
Related errors
- write not supported
- deadline not supported
- deadline not supported
- read not supported
- write not supported
AI-assisted analysis of ginuerzh/gost@a33fdbf4c9 (2026-09-02).
Data as JSON: /api/errors/52089db9cde151b0.
Report an issue: GitHub.