grpc/grpc-go · warning
error getting raw connection: %v
Error message
error getting raw connection: %v
What it means
This error occurs in SetTCPUserTimeout when tcpconn.SyscallConn() fails to obtain the raw file descriptor for the TCP connection. SyscallConn provides access to the underlying socket fd needed to set TCP_USER_TIMEOUT via setsockopt. Failure typically indicates the connection is in a bad state or the runtime cannot extract the fd.
Source
Thrown at internal/syscall/syscall_linux.go:79
stimeDiffus = latest.Stime.Usec - first.Stime.Usec
)
uTimeElapsed := float64(utimeDiffs) + float64(utimeDiffus)*1.0e-6
sTimeElapsed := float64(stimeDiffs) + float64(stimeDiffus)*1.0e-6
return uTimeElapsed, sTimeElapsed
}
// SetTCPUserTimeout sets the TCP user timeout on a connection's socket
func SetTCPUserTimeout(conn net.Conn, timeout time.Duration) error {
tcpconn, ok := conn.(*net.TCPConn)
if !ok {
// not a TCP connection. exit early
return nil
}
rawConn, err := tcpconn.SyscallConn()
if err != nil {
return fmt.Errorf("error getting raw connection: %v", err)
}
err = rawConn.Control(func(fd uintptr) {
err = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT, int(timeout/time.Millisecond))
})
if err != nil {
return fmt.Errorf("error setting option on socket: %v", err)
}
return nil
}
// GetTCPUserTimeout gets the TCP user timeout on a connection's socket
func GetTCPUserTimeout(conn net.Conn) (opt int, err error) {
tcpconn, ok := conn.(*net.TCPConn)
if !ok {
err = fmt.Errorf("conn is not *net.TCPConn. got %T", conn)
return
}View on GitHub (pinned to 03255a9237)
Solutions
- Check for concurrent close/teardown of the connection that races with keepalive setup.
- Ensure the net.Conn passed to gRPC is a standard *net.TCPConn, not a wrapper that breaks SyscallConn.
- If using a custom dialer, verify it returns real TCP connections.
- On non-critical errors, the transport setup will fail — review the transport logs for the root cause.
Example fix
// before (broken): custom dialer wraps TCPConn, breaking SyscallConn
dialer := func(ctx context.Context, addr string) (net.Conn, error) {
c, err := net.Dial("tcp", addr)
return &myWrapper{c}, err // SyscallConn() broken
}
// after (valid): return the raw *net.TCPConn
dialer := func(ctx context.Context, addr string) (net.Conn, error) {
return net.Dial("tcp", addr) // returns *net.TCPConn, SyscallConn works
} Defensive patterns
Strategy: try-catch
Validate before calling
// Verify the connection is a healthy *net.TCPConn before setting timeout
func safeSetTCPUserTimeout(conn net.Conn, timeout time.Duration) error {
tcp, ok := conn.(*net.TCPConn)
if !ok { return nil // not TCP, skip silently like SetTCPUserTimeout does
}
if tcp.RemoteAddr() == nil { return fmt.Errorf("connection has no remote addr") }
return syscall.SetTCPUserTimeout(conn, timeout)
} Type guard
func isTCPConn(conn net.Conn) bool {
_, ok := conn.(*net.TCPConn)
return ok
} Try / catch
if err := syscall.SetTCPUserTimeout(conn, kp.Timeout); err != nil {
if strings.Contains(err.Error(), "raw connection") {
// connection may be closing; non-fatal in some paths
log.Printf("warning: could not set TCP_USER_TIMEOUT: %v", err)
}
} Prevention
- Avoid wrapping *net.TCPConn in custom types that lose SyscallConn support.
- Ensure connections are not closed concurrently with transport setup.
- Use standard net.Dial for TCP connections passed to gRPC.
When it happens
Trigger: During gRPC server or client transport setup, SetTCPUserTimeout is called on a *net.TCPConn and SyscallConn() returns an error. This can happen if the connection's file descriptor has already been closed or put into an unusable state by the Go runtime.
Common situations: Connection closed concurrently (race between transport setup and teardown), Go runtime netpoller issues, or the connection is backed by a non-standard net.Conn wrapper that doesn't properly implement SyscallConn.
Related errors
- error setting option on socket: %v
- error getting option on socket: %v
- conn is not *net.TCPConn. got %T
- keepalive ping not acked within timeout %s
- no SubConn is available
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/3f56c5a914b4e3b4.
Report an issue: GitHub.