quarkusio/quarkus · error · IllegalStateException

Unable to find the GrpcClientConfigProvider

Error message

Unable to find the GrpcClientConfigProvider

What it means

Channels.createChannel resolves gRPC client configuration at runtime through the GrpcClientConfigProvider bean registered in the CDI container. If the Arc container has no GrpcClientConfigProvider bean available, channel creation cannot read quarkus.grpc.clients.* config and fails fast with IllegalStateException. This normally means the Quarkus gRPC deployment-time wiring did not run (e.g. code executed outside a Quarkus application, or in tests without the gRPC extension).

Source

Thrown at extensions/grpc/runtime/src/main/java/io/quarkus/grpc/runtime/supports/Channels.java:88

import io.vertx.grpcio.client.GrpcIoClient;
import io.vertx.grpcio.client.GrpcIoClientChannel;

@SuppressWarnings({ "OptionalIsPresent" })
public class Channels {

    private static final Logger LOGGER = Logger.getLogger(Channels.class.getName());

    private Channels() {
        // Avoid direct instantiation
    }

    @SuppressWarnings("rawtypes")
    public static Channel createChannel(String name, Set<String> perClientInterceptors) throws Exception {
        ArcContainer container = Arc.container();

        InstanceHandle<GrpcClientConfigProvider> instance = container.instance(GrpcClientConfigProvider.class);
        if (!instance.isAvailable()) {
            throw new IllegalStateException("Unable to find the GrpcClientConfigProvider");
        }
        instance.get();

        SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class);
        GrpcConfiguration grpcConfig = config.getConfigMapping(GrpcConfiguration.class);
        GrpcClientConfiguration clientConfig = grpcConfig.clients().get(name);

        String host = clientConfig.host();
        int port = clientConfig.port();
        if (LaunchMode.current() == LaunchMode.TEST) {
            if (clientConfig.testPort().isPresent()) {
                port = clientConfig.testPort().getAsInt();
            } else {
                boolean clientUsesTls = clientConfig.tlsConfigurationName().isPresent() || clientConfig.tls().enabled()
                        || (clientConfig.plainText().isPresent() && !clientConfig.plainText().get());
                ValueRegistry valueRegistry = container.instance(ValueRegistry.class).get();
                HttpServer httpServer = valueRegistry.get(HttpServer.HTTP_SERVER);
                int actualPort = clientUsesTls ? httpServer.getSecurePort() : httpServer.getPort();

View on GitHub (pinned to e1c734241f)

Solutions

  1. Run the code inside a Quarkus application / @QuarkusTest so the GrpcClientConfigProvider bean is registered by the gRPC extension.
  2. Obtain channels through the supported API: @Inject GrpcClient / Mutiny gRPC service stubs instead of calling Channels.createChannel manually.
  3. Add the quarkus-grpc extension dependency to the module (the provider is registered by the deployment module at build time).
  4. If in a test, annotate with @QuarkusTest and let the container start before creating clients.

Example fix

// before
Channel ch = Channels.createChannel("hello", Set.of());

// after
@QuarkusTest
class MyTest {
  @InjectMock
  // or better:
  @GrpcClient("hello")
  Greeter greeter; // managed channel created by Quarkus
}
Defensive patterns

Strategy: type-guard

Type guard

boolean grpcConfigAvailable() {
    io.quarkus.arc.ArcContainer container = io.quarkus.arc.Arc.container();
    return container != null
        && container.instance(io.quarkus.grpc.runtime.config.GrpcClientConfigProvider.class).isAvailable();
}

Try / catch

try {
    Channel ch = Channels.createChannel("hello", Set.of());
} catch (IllegalStateException e) {
    if (e.getMessage() != null && e.getMessage().contains("GrpcClientConfigProvider")) {
        throw new IllegalStateException("Channels.createChannel requires a running Quarkus app; use @GrpcClient injection instead", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling Channels.createChannel(name, perClientInterceptors) directly (or via code paths that build channels manually) when Arc.container().instance(GrpcClientConfigProvider.class).isAvailable() is false — typically running in a plain JUnit test, a non-Quarkus runtime, or an application where the gRPC deployment processor never registered the provider bean.

Common situations: Unit tests that instantiate gRPC clients without @QuarkusTest; using the gRPC runtime classes in a library consumed by a non-Quarkus app; startup ordering where the container is not yet initialized (Arc.container() null).

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/07f6abade2d89659. Report an issue: GitHub.