ginuerzh/gost · error · net.OpError

write not supported

Error message

write not supported

What it means

nopConn.Write always fails with a *net.OpError whose Err is 'write not supported'. The nop connection is a pure placeholder that performs no I/O, so writes (like reads) are rejected. It exists only to satisfy the net.Conn interface for discarded/placeholder traffic paths.

Source

Thrown at gost.go:163

	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
}

func (c *nopConn) SetDeadline(t time.Time) error {
	return &net.OpError{Op: "set", Net: "nop", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}

View on GitHub (pinned to a33fdbf4c9)

Solutions

  1. Don't write to nopConn — use it only where traffic should be dropped silently and discard the data yourself (io.Copy(io.Discard, src))
  2. If a writable sink is needed, use io.Discard via an adapter or a net.Pipe() endpoint
  3. Match on the *net.OpError Err ('write not supported') and treat as intentional discard
  4. Change nopConn (if in your fork) to return len(b), nil for silent drop semantics

Example fix

// before
io.Copy(nop, src) // errors: write not supported
// after
io.Copy(io.Discard, src) // intentionally drop the traffic
Defensive patterns

Strategy: type-guard

Validate before calling

if _, ok := conn.(*gostNopConn); ok {
    // discard instead of writing to nopConn
    io.Copy(io.Discard, src)
    return nil
}

Type guard

func isNopConn(c net.Conn) bool {
    return fmt.Sprintf("%T", c) == "*gost.nopConn"
}

Try / catch

_, err := conn.Write(data)
if err != nil {
    var oe *net.OpError
    if errors.As(err, &oe) && oe.Err.Error() == "write not supported" {
        return len(data), nil // treat as intentional discard
    }
    return err
}

Prevention

When it happens

Trigger: Any call to Write(b []byte) on a *nopConn, e.g. relaying data toward a connection that was replaced by a nopConn (traffic being discarded, bypassed hop, or test stub).

Common situations: io.Copy(dst, src) where dst is a nopConn in a two-way relay; sending responses through a discarded connection; tests writing into the stub.

Related errors


AI-assisted analysis of ginuerzh/gost@a33fdbf4c9 (2026-09-02). Data as JSON: /api/errors/0fffe5823ae221b9. Report an issue: GitHub.