ginuerzh/gost · warning · net.OpError

deadline not supported

Error message

deadline not supported

What it means

sshNopConn does not support deadlines: SetDeadline returns a *net.OpError (Op "set", Net "ssh") wrapping "deadline not supported". This stub exists because the nop conn has no real socket to arm; it signals that deadline-based timeout control is unavailable on this connection.

Source

Thrown at ssh.go:932

	return nil
}

func (c *sshNopConn) LocalAddr() net.Addr {
	return &net.TCPAddr{
		IP:   net.IPv4zero,
		Port: 0,
	}
}

func (c *sshNopConn) RemoteAddr() net.Addr {
	return &net.TCPAddr{
		IP:   net.IPv4zero,
		Port: 0,
	}
}

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

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

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

type sshConn struct {
	channel ssh.Channel
	conn    net.Conn
}

func (c *sshConn) Read(b []byte) (n int, err error) {
	return c.channel.Read(b)
}

View on GitHub (pinned to a33fdbf4c9)

Solutions

  1. Skip deadline setting when the conn is a sshNopConn (type-check or feature-detect before calling SetDeadline)
  2. Apply timeouts at a higher level (context.WithTimeout around the operation) instead of conn deadlines
  3. Swap the nop conn for the deadline-capable sshConn/underlying net.Conn if deadline enforcement is required

Example fix

// before
conn.SetDeadline(time.Now().Add(5*time.Second)) // panics into error on nop conn
// after
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
// do the operation with ctx
Defensive patterns

Strategy: fallback

Validate before calling

func supportsDeadlines(c net.Conn) bool {
    _, nop := c.(*sshNopConn)
    return !nop
}

Type guard

func withDeadline(c net.Conn, t time.Time) error {
    if _, nop := c.(*sshNopConn); nop { return nil } // skip, use context timeout instead
    return c.SetDeadline(t)
}

Try / catch

if err := conn.SetDeadline(time.Now().Add(5*time.Second)); err != nil {
    var opErr *net.OpError
    if errors.As(err, &opErr) && opErr.Net == "ssh" {
        // fall back to context-based timeout
        ctx, cancel = context.WithTimeout(ctx, 5*time.Second)
        defer cancel()
    } else { return err }
}

Prevention

When it happens

Trigger: Calling SetDeadline on a *sshNopConn, typically via a net.Conn-consumer that unconditionally sets deadlines before I/O (HTTP transports, deadline-wrapping helpers, net.Conn middleware).

Common situations: Wrapping the nop conn in a timeout container (e.g. a conn that enforces read/write deadlines); libraries that set deadlines as part of handshake or keepalive logic.

Related errors


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