{"record":{"id":"417580f69e7a9ecb","repo":"grpc/grpc-go","slug":"error-setting-option-on-socket-v","errorCode":null,"errorMessage":"error setting option on socket: %v","messagePattern":"error setting option on socket: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/syscall/syscall_linux.go","lineNumber":85,"sourceCode":"\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}\n\trawConn, err := tcpconn.SyscallConn()\n\tif err != nil {\n\t\terr = fmt.Errorf(\"error getting raw connection: %v\", err)\n\t\treturn\n\t}\n\terr = rawConn.Control(func(fd uintptr) {","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/syscall/syscall_linux.go#L67-L103","documentation":"Fires at syscall_linux.go:85 when either rawConn.Control or the syscall.SetsockoptInt inside its callback fails while setting the TCP_USER_TIMEOUT socket option. The callback approach is required because SyscallConn hands control of the fd to the function; any setsockopt failure (bad fd, permission, EINVAL) is reported here.","triggerScenarios":"SetsockoptInt(IPPROTO_TCP, TCP_USER_TIMEOUT, ms) fails inside rawConn.Control. Causes: EBADF if the fd is invalid by the time the callback runs, EINVAL for an out-of-range timeout (negative milliseconds after timeout/time.Millisecond truncation on extreme values), or ENOPROTOOPT on kernels without TCP_USER_TIMEOUT support.","commonSituations":"Very old kernels (pre-2.6.37) lacking TCP_USER_TIMEOUT; passing a negative or absurdly large timeout that truncates oddly; running under a seccomp/AppArmor profile that blocks setsockopt; a race where the socket closed between SyscallConn and Control.","solutions":["Confirm the timeout value is non-negative and reasonable (e.g. tens of seconds); avoid values that overflow when converted to milliseconds.","On old/embedded kernels, treat this error as non-fatal and fall back to gRPC's own keepalive/timeouts.","Check container/seccomp policy allows setsockopt; relax the filter if it blocks IPPROTO_TCP/TCP_USER_TIMEOUT.","Guard the call and log, since gRPC uses this only to detect dead peers faster."],"exampleFix":"// before\nif err := syscall.SetTCPUserTimeout(conn, -1*time.Second); err != nil {\n    return err   // negative -> truncates to huge uint -> EINVAL\n}\n\n// after\nif err := syscall.SetTCPUserTimeout(conn, 30*time.Second); err != nil {\n    log.Printf(\"TCP_USER_TIMEOUT unsupported on this kernel: %v\", err)\n}","handlingStrategy":"try-catch","validationCode":"// Guard against absurd timeout values that truncate badly.\nif timeout < 0 || timeout > math.MaxInt32*time.Millisecond {\n    return fmt.Errorf(\"refusing extreme TCP timeout %s\", timeout)\n}","typeGuard":null,"tryCatchPattern":"if err := syscall.SetTCPUserTimeout(conn, timeout); err != nil {\n    if errors.Is(err, syscall.ENOPROTOOPT) {\n        // kernel lacks TCP_USER_TIMEOUT; fall back to gRPC keepalive\n        log.Printf(\"TCP_USER_TIMEOUT unsupported: %v\", err)\n    } else {\n        return err\n    }\n}","preventionTips":["Use non-negative, modest timeout values (seconds, not exotic magnitudes).","On old kernels, fall back to gRPC keepalive params.","Check seccomp/AppArmor profiles permit setsockopt."],"tags":["syscall","tcp","linux","socket","timeout","setsockopt"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}