{"record":{"id":"4e4118e8423e6d2b","repo":"grpc/grpc-go","slug":"conn-is-not-net-tcpconn-got-t","errorCode":null,"errorMessage":"conn is not *net.TCPConn. got %T","messagePattern":"conn is not \\*net\\.TCPConn\\. got %T","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"info","filePath":"internal/syscall/syscall_linux.go","lineNumber":95,"sourceCode":"\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) {\n\t\topt, err = syscall.GetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT)\n\t})\n\tif err != nil {\n\t\terr = fmt.Errorf(\"error getting option on socket: %v\", err)\n\t\treturn\n\t}\n\n\treturn\n}\n","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/internal/syscall/syscall_linux.go#L77-L113","documentation":"This error occurs in GetTCPUserTimeout when the provided net.Conn is not a *net.TCPConn. Unlike SetTCPUserTimeout (which silently returns nil for non-TCP conns), GetTCPUserTimeout explicitly errors. This is used to read the current TCP_USER_TIMEOUT value, typically for diagnostics/channelz.","triggerScenarios":"GetTCPUserTimeout is called with a net.Conn that is not *net.TCPConn — e.g., a unix socket connection, a TLS connection wrapper, or a custom net.Conn type. The type assertion fails and the error reports the actual concrete type.","commonSituations":"gRPC server configured with a Unix domain socket listener (unix:///path) where channelz or diagnostic code attempts to read TCP keepalive settings, or a custom transport that provides a non-TCP underlying connection.","solutions":["If using Unix domain sockets, this error is expected and benign — TCP options don't apply.","If you expect a TCP connection, verify the listener/dialer configuration isn't using a non-TCP transport.","Suppress or ignore this error for non-TCP transports in diagnostic code paths."],"exampleFix":"// before (broken): expecting TCP keepalive on a unix socket connection\nlis, _ := net.Listen(\"unix\", \"/tmp/grpc.sock\")\n// GetTCPUserTimeout(conn) → \"conn is not *net.TCPConn. got *net.UnixConn\"\n\n// after (valid): check connection type before calling\nif _, ok := conn.(*net.TCPConn); ok {\n    timeout, err := syscall.GetTCPUserTimeout(conn)\n    // use timeout...\n} else {\n    // non-TCP connection; TCP options not applicable\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func isTCPConn(conn net.Conn) (*net.TCPConn, bool) {\n    tcp, ok := conn.(*net.TCPConn)\n    return tcp, ok\n}\n\n// Usage:\n// if tcp, ok := isTCPConn(conn); ok {\n//     timeout, err := syscall.GetTCPUserTimeout(tcp)\n// }","tryCatchPattern":"if _, err := syscall.GetTCPUserTimeout(conn); err != nil {\n    if strings.Contains(err.Error(), \"not *net.TCPConn\") {\n        // expected for unix sockets or non-TCP transports; ignore\n        return\n    }\n    log.Printf(\"error reading TCP_USER_TIMEOUT: %v\", err)\n}","preventionTips":["Type-check the connection before calling GetTCPUserTimeout in diagnostic code.","Expect this error for Unix domain socket and other non-TCP transports.","Suppress benign non-TCP connection errors in metrics/diagnostic collection."],"tags":["syscall","tcp","socket","type-check","diagnostics"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}