grpc/grpc-java · info · UnsupportedOperationException

Unsupported operation setSoLinger()

Error message

Unsupported operation setSoLinger()

What it means

setSoLinger() configures TCP SO_LINGER behavior on close (block until unsent data is flushed or discarded after N seconds). Unix domain sockets do not support this option, so UdsSocket throws UnsupportedOperationException.

Solutions

  1. Remove the setSoLinger call for UDS channels; close semantics are handled by the LocalSocket/stream layer
  2. Centralize socket-option setting in one type-aware helper that skips TCP-only options
  3. Catch UnsupportedOperationException around option setting so cleanup paths don't fail

Example fix

// before
socket.setSoLinger(true, 0); // hard close
// after
if (socket.getClass() != io.grpc.android.UdsSocket.class) {
  socket.setSoLinger(true, 0);
}
Defensive patterns

Strategy: try-catch

Validate before calling

boolean supportsLinger = !(socket instanceof io.grpc.android.UdsSocket);

Type guard

static boolean supportsSoLinger(java.net.Socket s) { return !(s instanceof io.grpc.android.UdsSocket); }

Try / catch

try { socket.setSoLinger(on, linger); } catch (UnsupportedOperationException e) { /* not applicable on UDS */ }

Prevention

When it happens

Trigger: Direct call to UdsSocket.setSoLinger(boolean,int), or connection-teardown tuning code that sets linger on all sockets it manages.

Common situations: Applying aggressive-close/linger tuning (e.g. setSoLinger(true, 0)) from TCP experience to a UDS gRPC channel; shared socket factory classes.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08). Data as JSON: /api/errors/044a5c27b4abefb1. Report an issue: GitHub.

Appendix: source

Thrown at android/src/main/java/io/grpc/android/UdsSocket.java:273

  }

  @Override
  public void setReuseAddress(boolean on) {
    throw new UnsupportedOperationException("Unsupported operation setReuseAddress()");
  }

  @Override
  public void setSendBufferSize(int size) throws SocketException {
    try {
      localSocket.setSendBufferSize(size);
    } catch (IOException e) {
      throw toSocketException(e);
    }
  }

  @Override
  public void setSoLinger(boolean on, int linger) {
    throw new UnsupportedOperationException("Unsupported operation setSoLinger()");
  }

  @Override
  public void setSoTimeout(int timeout) throws SocketException {
    try {
      localSocket.setSoTimeout(timeout);
    } catch (IOException e) {
      throw toSocketException(e);
    }
  }

  @Override
  public void setTcpNoDelay(boolean on) {
    // no-op
  }

  @Override
  public void setTrafficClass(int tc) {

View on GitHub (pinned to 64daddc1f3)