grpc/grpc-java · error · UnsupportedOperationException
call forAddress(String, int, CronetEngine) instead
Error message
call forAddress(String, int, CronetEngine) instead
What it means
CronetChannelBuilder.forAddress(String, int) is intentionally unimplemented. Cronet transport requires a CronetEngine to build streams, so the two-argument forAddress overload inherited from the generic builder API always throws UnsupportedOperationException. The annotated @DoNotCall marker signals compile-time discouragement as well.
Source
Thrown at cronet/src/main/java/io/grpc/cronet/CronetChannelBuilder.java:81
public static CronetChannelBuilder forAddress(String host, int port, CronetEngine cronetEngine) {
Preconditions.checkNotNull(cronetEngine, "cronetEngine");
return new CronetChannelBuilder(host, port, cronetEngine);
}
/**
* Always fails. Call {@link #forAddress(String, int, CronetEngine)} instead.
*/
@DoNotCall("Unsupported. Use forAddress(String, int, CronetEngine) instead")
public static CronetChannelBuilder forTarget(String target) {
throw new UnsupportedOperationException("call forAddress() instead");
}
/**
* Always fails. Call {@link #forAddress(String, int, CronetEngine)} instead.
*/
@DoNotCall("Unsupported. Use forAddress(String, int, CronetEngine) instead")
public static CronetChannelBuilder forAddress(String name, int port) {
throw new UnsupportedOperationException("call forAddress(String, int, CronetEngine) instead");
}
@Nullable
private ScheduledExecutorService scheduledExecutorService;
private final CronetEngine cronetEngine;
private final ManagedChannelImplBuilder managedChannelImplBuilder;
private final TransportTracer.Factory transportTracerFactory = TransportTracer.getDefaultFactory();
private boolean alwaysUsePut = false;
private int maxMessageSize = DEFAULT_MAX_MESSAGE_SIZE;
/**
* If true, indicates that the transport may use the GET method for RPCs, and may include the
* request body in the query params.
*/
private final boolean useGetForSafeMethods = false;View on GitHub (pinned to 64daddc1f3)
Solutions
- Use CronetChannelBuilder.forAddress(name, port, cronetEngine), passing a constructed CronetEngine (e.g. new CronetEngine.Builder(context).build()).
- If you have a target URI, use forTarget(String) with the engine-configured builder instead.
- Replace the Cronet transport with another transport (e.g. OkHttpChannelBuilder) if an engine cannot be supplied.
Example fix
// before
ManagedChannel ch = CronetChannelBuilder.forAddress("example.com", 443).build();
// after
CronetEngine engine = new CronetEngine.Builder(context).build();
ManagedChannel ch = CronetChannelBuilder.forAddress("example.com", 443, engine).build(); Defensive patterns
Strategy: validation
Validate before calling
if (engine == null) throw new IllegalArgumentException("CronetEngine required: use forAddress(name, port, engine)"); Prevention
- Always use the three-argument forAddress overload with a CronetEngine
- Heed @DoNotCall annotations and IDE warnings
- Centralize channel creation in one factory method
When it happens
Trigger: Calling CronetChannelBuilder.forAddress(host, port) directly instead of the three-argument overload forAddress(String name, int port, CronetEngine cronetEngine).
Common situations: Migrating generic gRPC channel-building code (written for netty or okHttp) to Cronet without adapting to the CronetEngine requirement; copying builder setup from docs for other transports.
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
- call forAddress() instead
- Unsupported operation getPort()
- call forAddress(AndroidComponentAddress, Context) instead
- call forAddress() instead
- TLS not supported in BinderServer
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/774c0cb69e479aa7.
Report an issue: GitHub.