grpc/grpc-java · error · UnsupportedOperationException

call forAddress() instead

Error message

call forAddress() instead

What it means

BinderServerBuilder.forPort(int port) is intentionally unsupported: a Binder gRPC server listens via an IBinder handed to an IBinderReceiver for an Android component, not a TCP port. The @DoNotCall method always throws UnsupportedOperationException directing you to forAddress(AndroidComponentAddress, IBinderReceiver).

Source

Thrown at binder/src/main/java/io/grpc/binder/BinderServerBuilder.java:58

   * Creates a server builder that will listen for bindings to the specified address.
   *
   * <p>The listening {@link IBinder} associated with new {@link Server}s will be stored in {@code
   * binderReceiver} upon {@link #build()}. Callers should return it from {@link
   * Service#onBind(Intent)} when the binding intent matches {@code listenAddress}.
   *
   * @param listenAddress an Android Service and binding Intent associated with this server.
   * @param receiver an "out param" for the new {@link Server}'s listening {@link IBinder}
   * @return a new builder
   */
  public static BinderServerBuilder forAddress(
      AndroidComponentAddress listenAddress, IBinderReceiver receiver) {
    return new BinderServerBuilder(listenAddress, receiver);
  }

  /** Always fails. Call {@link #forAddress(AndroidComponentAddress, IBinderReceiver)} instead. */
  @DoNotCall("Unsupported. Use forAddress() instead")
  public static BinderServerBuilder forPort(int port) {
    throw new UnsupportedOperationException("call forAddress() instead");
  }

  private final ServerImplBuilder serverImplBuilder;
  private final BinderServer.Builder internalBuilder = new BinderServer.Builder();
  private boolean isBuilt;

  private BinderServerBuilder(
      AndroidComponentAddress listenAddress, IBinderReceiver binderReceiver) {
    internalBuilder.setListenAddress(listenAddress);

    serverImplBuilder =
        new ServerImplBuilder(
            (streamTracerFactories, metricRecorder) -> {
              internalBuilder.setStreamTracerFactories(streamTracerFactories);
              BinderServer server = internalBuilder.build();
              BinderInternal.setIBinder(binderReceiver, server.getHostBinder());
              return server;
            });

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Use BinderServerBuilder.forAddress(AndroidComponentAddress, IBinderReceiver) instead
  2. Provide an IBinderReceiver implementation that receives the listening IBinder for publishing via the Android component

Example fix

// before
Server server = BinderServerBuilder.forPort(50051).build();
// after
Server server = BinderServerBuilder.forAddress(
    AndroidComponentAddress.forComponent(componentName), ibinderReceiver)
    .addService(myService).build();
Defensive patterns

Strategy: validation

Validate before calling

if (listenAddress instanceof AndroidComponentAddress) {
  server = BinderServerBuilder.forAddress((AndroidComponentAddress) listenAddress, receiver).build();
} else {
  server = ServerBuilder.forPort(port).addService(service).build();
}

Type guard

static boolean isBinderListenAddress(SocketAddress addr) {
  return addr instanceof AndroidComponentAddress;
}

Try / catch

try {
  return BinderServerBuilder.forAddress(componentAddr, receiver).addService(svc).build();
} catch (UnsupportedOperationException e) {
  throw new IllegalStateException("Binder servers use forAddress(AndroidComponentAddress, IBinderReceiver)", e);
}

Prevention

When it happens

Trigger: Calling BinderServerBuilder.forPort(50051) — typically ported ServerBuilder.forPort(...) code on the binder transport.

Common situations: Refactoring an on-device TCP gRPC server to binder IPC while keeping ServerBuilder.forPort; template code that assumes port-based servers.

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/4d21b8729861ae56. Report an issue: GitHub.