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

  1. Use CronetChannelBuilder.forAddress(name, port, cronetEngine), passing a constructed CronetEngine (e.g. new CronetEngine.Builder(context).build()).
  2. If you have a target URI, use forTarget(String) with the engine-configured builder instead.
  3. 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

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


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