grpc/grpc-java · error · IllegalArgumentException

At least one credential is required

Error message

At least one credential is required

What it means

ChoiceChannelCredentials.create() builds a credentials object that tries its options in preference order. It requires at least one credential; calling create() with an empty varargs array throws IllegalArgumentException before any null check.

Source

Thrown at api/src/main/java/io/grpc/ChoiceChannelCredentials.java:37

import static java.util.Collections.unmodifiableList;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Provides a list of {@link ChannelCredentials}, where any one may be used. The credentials are in
 * preference order.
 */
public final class ChoiceChannelCredentials extends ChannelCredentials {
  /**
   * Constructs with the provided {@code creds} as options, with preferred credentials first.
   *
   * @throws IllegalArgumentException if no creds are provided
   */
  public static ChannelCredentials create(ChannelCredentials... creds) {
    if (creds.length == 0) {
      throw new IllegalArgumentException("At least one credential is required");
    }
    for (ChannelCredentials cred : creds) {
      if (cred == null) {
        throw new NullPointerException();
      }
    }
    return new ChoiceChannelCredentials(unmodifiableList(new ArrayList<>(Arrays.asList(creds))));
  }

  private final List<ChannelCredentials> creds;

  private ChoiceChannelCredentials(List<ChannelCredentials> creds) {
    this.creds = creds;
  }

  /** Non-empty list of credentials, in preference order. */
  public List<ChannelCredentials> getCredentialsList() {
    return creds;

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Ensure at least one ChannelCredentials is always provided, e.g. prepend a fallback like TlsChannelCredentials.create() or InsecureChannelCredentials.create()
  2. Validate the credential list is non-empty before calling create() and surface a clear configuration error
  3. Fix the configuration source so the credentials section is populated (cert/key files present)

Example fix

// before
ChannelCredentials creds = ChoiceChannelCredentials.create(configuredCreds.toArray(new ChannelCredentials[0]));
// after
if (configuredCreds.isEmpty()) {
  configuredCreds.add(InsecureChannelCredentials.create()); // or fail fast with a config error
}
ChannelCredentials creds = ChoiceChannelCredentials.create(configuredCreds.toArray(new ChannelCredentials[0]));
Defensive patterns

Strategy: validation

Validate before calling

if (credList == null || credList.isEmpty()) {
  throw new IllegalArgumentException("At least one ChannelCredentials must be configured");
}
ChannelCredentials creds = ChoiceChannelCredentials.create(credList.toArray(new ChannelCredentials[0]));

Try / catch

try {
  ChannelCredentials creds = ChoiceChannelCredentials.create(credArray);
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("At least one credential is required")) {
    creds = InsecureChannelCredentials.create(); // or surface a config error
  } else throw e;
}

Prevention

When it happens

Trigger: Calling ChannelCredentials.create() / ChoiceChannelCredentials.create() with zero arguments, e.g. from a spread of an empty collection like creds.toArray(new ChannelCredentials[0]) where the list is empty, or omitting arguments entirely.

Common situations: Dynamically building a credential list from configuration (TLS disabled or keys absent) and passing the (possibly empty) result; a config file whose credential section was dropped; refactoring that removed the default fallback credential.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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