grpc/grpc-java · error · RemoteException

BinderProxy#transact(code, FLAG_ONEWAY) returned false

Error message

BinderProxy#transact(code, FLAG_ONEWAY) returned false

What it means

OneWayBinderProxy.transact sends a FLAG_ONEWAY binder transaction; per the Android binder contract a oneway transact should never return false. If BinderProxy#transact nevertheless reports false, the proxy throws a RemoteException so the caller treats it as an ordinary transport-layer error.

Source

Thrown at binder/src/main/java/io/grpc/binder/internal/OneWayBinderProxy.java:116

  /**
   * Returns the wrapped {@link IBinder} for the purpose of calling methods other than {@link
   * IBinder#transact(int, Parcel, Parcel, int)}.
   */
  public IBinder getDelegate() {
    return delegate;
  }

  static class OutOfProcessImpl extends OneWayBinderProxy {
    OutOfProcessImpl(IBinder iBinder) {
      super(iBinder);
    }

    @Override
    public void transact(int code, ParcelHolder data) throws RemoteException {
      if (!transactAndRecycleParcel(code, data.release())) {
        // This cannot happen (see g/android-binder/c/jM4NvS234Rw) but, just in case, let the caller
        // handle it along with all the other possible transport-layer errors.
        throw new RemoteException("BinderProxy#transact(" + code + ", FLAG_ONEWAY) returned false");
      }
    }
  }

  protected boolean transactAndRecycleParcel(int code, Parcel data) throws RemoteException {
    try {
      return delegate.transact(code, data, null, IBinder.FLAG_ONEWAY);
    } finally {
      data.recycle();
    }
  }

  static class InProcessImpl extends OneWayBinderProxy {
    private final SerializingExecutor executor;

    InProcessImpl(IBinder binder, Executor executor) {
      super(binder);
      this.executor = new SerializingExecutor(executor);

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Catch the RemoteException in the RPC caller and let gRPC's transport error handling fail/retry the call as with any transport error.
  2. Retry the transaction; if it repeats, rebind to the remote service (the binder object may be stale).
  3. If reproducible, report it upstream (see the referenced binder bug thread) since it violates the oneway transact contract.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  proxy.transact(code, data);
} catch (RemoteException e) {
  // treat as transport error: rebind to service and/or retry
}

Prevention

When it happens

Trigger: A FLAG_ONEWAY transaction through BinderProxy#transact returns false - an unexpected binder-driver outcome documented as practically impossible, but guarded here so callers can handle it with all other transport errors.

Common situations: Binder driver anomalies or kernel/device-specific issues during a oneway call between an Android app and a remote service; practically never hit in normal code paths.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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