grpc/grpc-java · error · IllegalArgumentException

${result.error}

Error message

${result.error}

What it means

InternalNettyChannelCredentials.toNegotiator() converts arbitrary ChannelCredentials via ProtocolNegotiators.from(), which returns a result object with an error string instead of throwing. If the credentials type is unsupported, the error string is wrapped in an IllegalArgumentException.

Source

Thrown at netty/src/main/java/io/grpc/netty/InternalNettyChannelCredentials.java:45

public final class InternalNettyChannelCredentials {
  private InternalNettyChannelCredentials() {}

  /** Creates a {@link ChannelCredentials} that will use the provided {@code negotiator}. */
  public static ChannelCredentials create(InternalProtocolNegotiator.ClientFactory negotiator) {
    return NettyChannelCredentials.create(negotiator);
  }

  /**
   * Converts a {@link ChannelCredentials} to a negotiator, in similar fashion as for a new channel.
   *
   * @throws IllegalArgumentException if unable to convert
   */
  public static InternalProtocolNegotiator.ClientFactory toNegotiator(
      ChannelCredentials channelCredentials) {
    final ProtocolNegotiators.FromChannelCredentialsResult result =
        ProtocolNegotiators.from(channelCredentials);
    if (result.error != null) {
      throw new IllegalArgumentException(result.error);
    }
    final class ClientFactory implements InternalProtocolNegotiator.ClientFactory {

      @Override
      public InternalProtocolNegotiator.ProtocolNegotiator newNegotiator() {
        return new InternalProtocolNegotiator.ProtocolNegotiatorAdapter(
            result.negotiator.newNegotiator());
      }

      @Override
      public int getDefaultPort() {
        return result.negotiator.getDefaultPort();
      }
    }

    return new ClientFactory();
  }
}

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Use NettyChannelCredentials TLS credentials or InsecureChannelCredentials with the Netty transport
  2. Check the credentials were produced by NettyChannelCredentials/Plaintext APIs, not another transport's builder
  3. Wrap in the transport-appropriate credentials type before calling toNegotiator

Example fix

// before
InternalNettyChannelCredentials.toNegotiator(otherTransportCreds);
// after
InternalNettyChannelCredentials.toNegotiator(TlsChannelCredentials.newBuilder().build());
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(creds instanceof TlsChannelCredentials) && !(creds instanceof InsecureChannelCredentials)) { throw new IllegalArgumentException("Unsupported ChannelCredentials for Netty"); }

Type guard

boolean nettyCompatible(ChannelCredentials c) { return c instanceof TlsChannelCredentials || c instanceof InsecureChannelCredentials; }

Try / catch

try { return InternalNettyChannelCredentials.toNegotiator(creds); } catch (IllegalArgumentException e) { log.error("Unsupported credentials: " + e.getMessage()); throw e; }

Prevention

When it happens

Trigger: Passing a ChannelCredentials that ProtocolNegotiators.from() cannot handle (e.g. a custom or composite credentials type unknown to the Netty transport) into InternalNettyChannelCredentials.toNegotiator().

Common situations: Mixing credentials from a different transport (e.g. in-process or okhttp credentials) into a Netty channel; custom ChannelCredentials implementations; internal API misuse when building custom transports.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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