{"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/0c51461d27177d997e14c642fe18c11668fc09a3/internal/syscall/syscall_linux.go#L61-L97","documentation":"Fires at syscall_linux.go:79 when (*net.TCPConn).SyscallConn() returns an error inside SetTCPUserTimeout. SyscallConn yields the raw OS file descriptor so the code can call setsockopt(TCP_USER_TIMEOUT); if it fails, gRPC cannot obtain the fd to set the option and surfaces the cause. The connection itself may still be usable for data, just without the user-timeout behavior.","triggerScenarios":"Calling SetTCPUserTimeout on a *net.TCPConn whose underlying fd is unavailable. Typical causes: the connection is already closed; the net.Conn was wrapped by a custom dialer that doesn't expose a real fd; running under a constrained environment (some sandboxes/seccomp filters) where fd access is blocked.","commonSituations":"Custom net.Dialer wrappers or connection-pool layers that return a *net.TCPConn alias over a non-TCP transport; calling SetTCPUserTimeout after the connection errored/closed; rare kernel/Gvisor environments where SyscallConn is not supported.","solutions":["Check whether the conn is still open before calling SetTCPUserTimeout; ignore the error if you only set the timeout opportunistically.","If you wrapped the connection, ensure the wrapper embeds/proxies *net.TCPConn so SyscallConn works.","On Linux, confirm the fd is a real TCP socket; SetTCPUserTimeout is a no-op (returns nil) for non-TCP types, so a non-nil error here means the type assertion passed but SyscallConn failed."],"exampleFix":"// before\nif err := syscall.SetTCPUserTimeout(conn, 30*time.Second); err != nil {\n    return err   // fatal: aborts connection setup\n}\n\n// after (treat as best-effort)\nif err := syscall.SetTCPUserTimeout(conn, 30*time.Second); err != nil {\n    log.Printf(\"could not set TCP_USER_TIMEOUT: %v\", err)\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"// Only attempt TCP_USER_TIMEOUT on real TCP connections.\nif _, ok := conn.(*net.TCPConn); !ok {\n    return // not TCP; SetTCPUserTimeout is a no-op anyway\n}","tryCatchPattern":"if err := syscall.SetTCPUserTimeout(conn, timeout); err != nil {\n    // SyscallConn failed; treat as best-effort, do not abort the connection\n    log.Printf(\"SetTCPUserTimeout (getConn) skipped: %v\", err)\n}","preventionTips":["Treat SetTCPUserTimeout as opportunistic; log and continue on failure.","Ensure custom dialers return real *net.TCPConn values.","Don't call it on an already-closed connection."],"tags":["syscall","tcp","linux","socket","timeout"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}