{"record":{"id":"3f56c5a914b4e3b4","repo":"grpc/grpc-go","slug":"error-getting-raw-connection-v","errorCode":null,"errorMessage":"error getting raw connection: %v","messagePattern":"error getting raw connection: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/syscall/syscall_linux.go","lineNumber":79,"sourceCode":"\t\tstimeDiffus = latest.Stime.Usec - first.Stime.Usec\n\t)\n\n\tuTimeElapsed := float64(utimeDiffs) + float64(utimeDiffus)*1.0e-6\n\tsTimeElapsed := float64(stimeDiffs) + float64(stimeDiffus)*1.0e-6\n\n\treturn uTimeElapsed, sTimeElapsed\n}\n\n// SetTCPUserTimeout sets the TCP user timeout on a connection's socket\nfunc SetTCPUserTimeout(conn net.Conn, timeout time.Duration) error {\n\ttcpconn, ok := conn.(*net.TCPConn)\n\tif !ok {\n\t\t// not a TCP connection. exit early\n\t\treturn nil\n\t}\n\trawConn, err := tcpconn.SyscallConn()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error getting raw connection: %v\", err)\n\t}\n\terr = rawConn.Control(func(fd uintptr) {\n\t\terr = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT, int(timeout/time.Millisecond))\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error setting option on socket: %v\", err)\n\t}\n\n\treturn nil\n}\n\n// GetTCPUserTimeout gets the TCP user timeout on a connection's socket\nfunc GetTCPUserTimeout(conn net.Conn) (opt int, err error) {\n\ttcpconn, ok := conn.(*net.TCPConn)\n\tif !ok {\n\t\terr = fmt.Errorf(\"conn is not *net.TCPConn. got %T\", conn)\n\t\treturn\n\t}","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/internal/syscall/syscall_linux.go#L61-L97","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (broken): custom dialer wraps TCPConn, breaking SyscallConn\ndialer := func(ctx context.Context, addr string) (net.Conn, error) {\n    c, err := net.Dial(\"tcp\", addr)\n    return &myWrapper{c}, err // SyscallConn() broken\n}\n\n// after (valid): return the raw *net.TCPConn\ndialer := func(ctx context.Context, addr string) (net.Conn, error) {\n    return net.Dial(\"tcp\", addr) // returns *net.TCPConn, SyscallConn works\n}","handlingStrategy":"try-catch","validationCode":"// Verify the connection is a healthy *net.TCPConn before setting timeout\nfunc safeSetTCPUserTimeout(conn net.Conn, timeout time.Duration) error {\n    tcp, ok := conn.(*net.TCPConn)\n    if !ok { return nil // not TCP, skip silently like SetTCPUserTimeout does\n    }\n    if tcp.RemoteAddr() == nil { return fmt.Errorf(\"connection has no remote addr\") }\n    return syscall.SetTCPUserTimeout(conn, timeout)\n}","typeGuard":"func isTCPConn(conn net.Conn) bool {\n    _, ok := conn.(*net.TCPConn)\n    return ok\n}","tryCatchPattern":"if err := syscall.SetTCPUserTimeout(conn, kp.Timeout); err != nil {\n    if strings.Contains(err.Error(), \"raw connection\") {\n        // connection may be closing; non-fatal in some paths\n        log.Printf(\"warning: could not set TCP_USER_TIMEOUT: %v\", err)\n    }\n}","preventionTips":["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."],"tags":["syscall","tcp","socket","linux","keepalive","connection"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}