grpc/grpc-java · error · UnsupportedOperationException
ClientTransportFactoryBuilder is required, use a constructor
Error message
ClientTransportFactoryBuilder is required, use a constructor
What it means
ManagedChannelImplBuilder extends ManagedChannelBuilder but is internal; unlike public builders it requires a ClientTransportFactory (supplied via a constructor or transport builder) to know how to create connections. The inherited static forAddress() factory method is annotated @DoNotCall and always throws UnsupportedOperationException to steer users to the correct constructors.
Source
Thrown at core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java:84
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
/**
* Default managed channel builder, for usage in Transport implementations.
*/
public final class ManagedChannelImplBuilder
extends ManagedChannelBuilder<ManagedChannelImplBuilder> {
private static final String DIRECT_ADDRESS_SCHEME = "directaddress";
private static final Logger log = Logger.getLogger(ManagedChannelImplBuilder.class.getName());
@DoNotCall("ClientTransportFactoryBuilder is required, use a constructor")
public static ManagedChannelBuilder<?> forAddress(String name, int port) {
throw new UnsupportedOperationException(
"ClientTransportFactoryBuilder is required, use a constructor");
}
@DoNotCall("ClientTransportFactoryBuilder is required, use a constructor")
public static ManagedChannelBuilder<?> forTarget(String target) {
throw new UnsupportedOperationException(
"ClientTransportFactoryBuilder is required, use a constructor");
}
/**
* An idle timeout larger than this would disable idle mode.
*/
@VisibleForTesting
static final long IDLE_MODE_MAX_TIMEOUT_DAYS = 30;
/**
* The default idle timeout.
*/View on GitHub (pinned to 64daddc1f3)
Solutions
- Use io.grpc.ManagedChannelBuilder.forAddress(name, port) (the public API) instead.
- If you truly need the internal builder, use its constructor with a ClientTransportFactoryBuilder argument.
- Fix the import statement so the public builder class is referenced.
Example fix
// before
import io.grpc.internal.ManagedChannelImplBuilder;
ManagedChannelBuilder<?> b = ManagedChannelImplBuilder.forAddress("localhost", 50051);
// after
import io.grpc.ManagedChannelBuilder;
ManagedChannelBuilder<?> b = ManagedChannelBuilder.forAddress("localhost", 50051); Defensive patterns
Strategy: type-guard
Validate before calling
Class<?> c = builder.getClass();
if (c.getName().equals("io.grpc.internal.ManagedChannelImplBuilder")) {
throw new IllegalStateException("Use io.grpc.ManagedChannelBuilder");
} Type guard
boolean isPublicBuilder(ManagedChannelBuilder<?> b) {
return !b.getClass().getName().startsWith("io.grpc.internal.");
} Try / catch
try {
return builder.forAddress(host, port);
} catch (UnsupportedOperationException e) {
if (e.getMessage().contains("ClientTransportFactoryBuilder")) {
return io.grpc.ManagedChannelBuilder.forAddress(host, port);
}
throw e;
} Prevention
- Import io.grpc.ManagedChannelBuilder, never io.grpc.internal.ManagedChannelImplBuilder, in app code.
- Add an import-order/lint rule banning io.grpc.internal imports outside grpc itself.
- Search codebase for 'ManagedChannelImplBuilder' usages when upgrading gRPC.
When it happens
Trigger: Calling ManagedChannelImplBuilder.forAddress(name, port) directly, e.g. via reflection or by mistyping the import so ManagedChannelImplBuilder is used instead of ManagedChannelBuilder.
Common situations: Import confusion between io.grpc.ManagedChannelBuilder and io.grpc.internal.ManagedChannelImplBuilder; framework code instantiating the internal builder through its static API.
Understand the failure class
Background: "is deprecated and will be removed" — deprecation warnings for old API names, keywords, and options, and how to migrate before the removal release — this error's family across 29 libraries.
Related errors
- ChannelLogger is not set in Builder
- NameResolverRegistry is not set in Builder
- No ALTS context information found
- Can't set TLS settings for ALTS
- Counter has overflowed.
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/ae06342226156784.
Report an issue: GitHub.