grpc/grpc-java · error · IllegalStateException

The transport factory is closed.

Error message

The transport factory is closed.

What it means

BinderClientTransportFactory.newClientTransport() checks its closed flag and throws IllegalStateException('The transport factory is closed.') when a new transport is requested after the factory has been shut down. The factory is closed when the owning channelbuilder/channel is disposed, so any late transport creation indicates the channel is being used after (or during) shutdown.

Source

Thrown at binder/src/main/java/io/grpc/binder/internal/BinderClientTransportFactory.java:87

    scheduledExecutorPool = checkNotNull(builder.scheduledExecutorPool);
    offloadExecutorPool = checkNotNull(builder.offloadExecutorPool);
    securityPolicy = checkNotNull(builder.securityPolicy);
    bindServiceFlags = checkNotNull(builder.bindServiceFlags);
    inboundParcelablePolicy = checkNotNull(builder.inboundParcelablePolicy);
    binderDecorator = checkNotNull(builder.binderDecorator);
    readyTimeoutMillis = builder.readyTimeoutMillis;
    preAuthorizeServers = builder.preAuthorizeServers;
    useLegacyAuthStrategy = builder.useLegacyAuthStrategy;

    executorService = scheduledExecutorPool.getObject();
    offloadExecutor = offloadExecutorPool.getObject();
  }

  @Override
  public BinderClientTransport newClientTransport(
      SocketAddress addr, ClientTransportOptions options, ChannelLogger channelLogger) {
    if (closed) {
      throw new IllegalStateException("The transport factory is closed.");
    }
    return new BinderClientTransport(this, (AndroidComponentAddress) addr, options);
  }

  @Override
  public ScheduledExecutorService getScheduledExecutorService() {
    return executorService;
  }

  @Override
  public SwapChannelCredentialsResult swapChannelCredentials(ChannelCredentials channelCreds) {
    return null;
  }

  @Override
  public void close() {
    if (closed) {
      return;

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Do not start new RPCs after calling shutdown()/shutdownNow() on the channel that owns the factory
  2. Await channel termination (awaitTermination) and recreate a fresh channel if further calls are needed
  3. Guard application code so lifecycle events (Android onDestroy/rebind) close the channel only when no calls will follow

Example fix

// before
channel.shutdown();
stub.call(request); // may hit closed factory
// after
channel.shutdown();
channel.awaitTermination(5, TimeUnit.SECONDS);
channel = BinderChannelBuilder.forAddress(addr, context).build();
stub.call(request);
Defensive patterns

Strategy: try-catch

Validate before calling

if (channel.isShutdown() || channel.isTerminated()) {
  channel = BinderChannelBuilder.forAddress(addr, context).build();
}
stub.call(request);

Type guard

static boolean isUsable(ManagedChannel ch) {
  return ch != null && !ch.isShutdown() && !ch.isTerminated();
}

Try / catch

try {
  stub.call(request);
} catch (IllegalStateException e) {
  if (e.getMessage() != null && e.getMessage().contains("transport factory is closed")) {
    channel = BinderChannelBuilder.forAddress(addr, context).build();
    stub = newStub(channel);
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling newClientTransport(...) on a BinderClientTransportFactory after close(); typically triggered when the channel attempts reconnect/transport creation after the channel (and its factory) has been closed.

Common situations: Using a ManagedChannel after shutdown(); concurrent shutdown while a call is still being placed; keeping a reference to a closed channel in a long-lived component (e.g. an Android Service recreated/rebound).

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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