{"record":{"id":"8f5c0cc723c53a2c","repo":"grpc/grpc-java","slug":"unsupported-operation-getkeepalive","errorCode":null,"errorMessage":"Unsupported operation getKeepAlive()","messagePattern":"Unsupported operation getKeepAlive\\(\\)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"android/src/main/java/io/grpc/android/UdsSocket.java","lineNumber":113,"sourceCode":"\n  @Override\n  public InetAddress getInetAddress() {\n    throw new UnsupportedOperationException(\"getInetAddress() not supported\");\n  }\n\n  @Override\n  public InputStream getInputStream() throws IOException {\n    return new FilterInputStream(localSocket.getInputStream()) {\n      @Override\n      public void close() throws IOException {\n        UdsSocket.this.close();\n      }\n    };\n  }\n\n  @Override\n  public boolean getKeepAlive() {\n    throw new UnsupportedOperationException(\"Unsupported operation getKeepAlive()\");\n  }\n\n  @Override\n  public InetAddress getLocalAddress() {\n    throw new UnsupportedOperationException(\"Unsupported operation getLocalAddress()\");\n  }\n\n  @Override\n  public int getLocalPort() {\n    throw new UnsupportedOperationException(\"Unsupported operation getLocalPort()\");\n  }\n\n  @Override\n  public SocketAddress getLocalSocketAddress() {\n    return new SocketAddress() {};\n  }\n\n  @Override","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/android/src/main/java/io/grpc/android/UdsSocket.java#L95-L131","documentation":"UdsSocket wraps Android LocalSocket, whose options differ from TCP sockets. TCP keep-alive has no equivalent configurable on the LocalSocket path used here, so getKeepAlive() throws UnsupportedOperationException by design. This is part of UdsSocket's pattern of rejecting unsupported java.net.Socket option accessors.","triggerScenarios":"Calling getKeepAlive() on the UdsSocket instance from UdsSocketFactory — e.g. framework code that reads back socket options after connect, or pooling/health-check logic reading keep-alive state.","commonSituations":"HTTP connection pool code that inspects keep-alive settings; libraries ported from TCP contexts that unconditionally read socket options; Android network-health instrumentation.","solutions":["Do not read or write TCP socket options on UDS sockets; rely on gRPC's own keepalive settings (ManagedChannelBuilder.keepAliveTime) at the channel level instead.","Guard option reads with a class check for UdsSocket and skip them for UDS transport.","Catch UnsupportedOperationException around option access if generic socket-handling code must remain shared."],"exampleFix":"// before\nboolean ka = socket.getKeepAlive();\n// after\nboolean ka = socket.getClass().getSimpleName().equals(\"UdsSocket\")\n    ? false\n    : socket.getKeepAlive();\n// gRPC-level keepalive instead:\n// builder.keepAliveTime(30, TimeUnit.SECONDS)","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"static boolean supportsTcpOptions(Socket s) {\n  return !s.getClass().getName().equals(\"io.grpc.android.UdsSocket\");\n}","tryCatchPattern":"try {\n  boolean ka = socket.getKeepAlive();\n} catch (UnsupportedOperationException e) {\n  // UDS socket: rely on gRPC channel-level keepAliveTime instead\n}","preventionTips":["Configure keepalive via ManagedChannelBuilder.keepAliveTime/keepAliveTimeout, not socket options.","Skip TCP option reads when the socket came from UdsSocketFactory.","Keep socket-option logic behind a capability-checking helper."],"tags":["grpc","android","unix-domain-socket","socket-options","unsupported"],"backgroundTag":"unsupported-operation","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}