grpc/grpc-java · error · IllegalStateException

The transport factory is closed.

Error message

The transport factory is closed.

What it means

OkHttpTransportFactory.newClientTransport throws IllegalStateException when the factory was already closed via close(). The factory is owned by the channel; using it after shutdown is a lifecycle violation.

Source

Thrown at okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java:861

      this.enableKeepAlive = enableKeepAlive;
      this.keepAliveTimeNanos = keepAliveTimeNanos;
      this.keepAliveBackoff = new AtomicBackoff("keepalive time nanos", keepAliveTimeNanos);
      this.keepAliveTimeoutNanos = keepAliveTimeoutNanos;
      this.flowControlWindow = flowControlWindow;
      this.keepAliveWithoutCalls = keepAliveWithoutCalls;
      this.maxInboundMetadataSize = maxInboundMetadataSize;
      this.useGetForSafeMethods = useGetForSafeMethods;
      this.channelCredentials = channelCredentials;

      this.transportTracerFactory =
          Preconditions.checkNotNull(transportTracerFactory, "transportTracerFactory");
    }

    @Override
    public ConnectionClientTransport newClientTransport(
        SocketAddress addr, ClientTransportOptions options, ChannelLogger channelLogger) {
      if (closed) {
        throw new IllegalStateException("The transport factory is closed.");
      }
      final AtomicBackoff.State keepAliveTimeNanosState = keepAliveBackoff.getState();
      Runnable tooManyPingsRunnable = new Runnable() {
        @Override
        public void run() {
          keepAliveTimeNanosState.backoff();
        }
      };
      InetSocketAddress inetSocketAddr = (InetSocketAddress) addr;
      // TODO(carl-mastrangelo): Pass channelLogger in.
      OkHttpClientTransport transport = new OkHttpClientTransport(
          this,
          inetSocketAddr,
          options.getAuthority(),
          options.getUserAgent(),
          options.getEagAttributes(),
          options.getHttpConnectProxiedSocketAddress(),
          tooManyPingsRunnable,

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Create a new channel (builder.build()) after shutdown instead of reusing the old one
  2. Guard application code with a check on channel.isShutdown()/isTerminated before issuing calls
  3. Do not close the transport factory while connections are still needed; manage the factory lifecycle with the channel
  4. Serialize shutdown logic so no requests are started concurrently with shutdown

Example fix

// before
channel.shutdownNow();
ManagedChannel c2 = channel; c2.getState(false); // new transport on closed factory
// after
channel.shutdownNow();
ManagedChannel c2 = OkHttpChannelBuilder.forAddress(host, port).build();
Defensive patterns

Strategy: type-guard

Validate before calling

if (channel.isShutdown() || channel.isTerminated()) { channel = rebuildChannel(); }

Type guard

ManagedChannel activeChannel(ManagedChannel ch, Supplier<ManagedChannel> rebuild) { return (ch.isShutdown() || ch.isTerminated()) ? rebuild.get() : ch; }

Try / catch

try { stub.call(req); } catch (IllegalStateException e) { if (e.getMessage().contains("transport factory is closed")) { channel = rebuildChannel(); stub = newStub(channel); } else { throw e; } }

Prevention

When it happens

Trigger: Calling newClientTransport after the channel/factory was shut down — e.g. creating RPCs on a channel after shutdownNow(), or reusing a shared OkHttpChannelBuilder transport factory across channel lifecycles.

Common situations: Application tries to make calls after channel.shutdown(); keeping a stale channel reference in a singleton after restart logic; race between shutdown and in-flight request creation.

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/64ffa2695ffe6e29. Report an issue: GitHub.