quarkusio/quarkus · error · IllegalArgumentException

Unsupported OTEL protocol:

Error message

Unsupported OTEL protocol: 

What it means

LgtmContainer.getPrivateOtlpPort() maps the configured OTLP protocol (grpc or http) to the corresponding exporter port inside the LGTM container. Any protocol value other than 'grpc'/'gRPC' or 'http' is unsupported and throws an IllegalArgumentException.

Source

Thrown at extensions/observability-devservices/testcontainers/src/main/java/io/quarkus/observability/testcontainers/LgtmContainer.java:182

        return new LgtmLoggingFilter();
    }

    public String getOtlpProtocol() {
        return config.otlpProtocol();
    }

    private int getPrivateOtlpPort() {
        return getPrivateOtlpPort(getOtlpProtocol());
    }

    public static int getPrivateOtlpPort(String otlpProtocol) {
        // use ignore-case here; grpc == gRPC
        if (ContainerConstants.OTEL_GRPC_PROTOCOL.equalsIgnoreCase(otlpProtocol)) {
            return ContainerConstants.OTEL_GRPC_EXPORTER_PORT;
        } else if (ContainerConstants.OTEL_HTTP_PROTOCOL.equals(otlpProtocol)) {
            return ContainerConstants.OTEL_HTTP_EXPORTER_PORT;
        } else {
            throw new IllegalArgumentException("Unsupported OTEL protocol: " + otlpProtocol);
        }
    }

    private String getPrometheusConfig() {
        String scraping = config.scrapingInterval() + "s";
        String prometheusConfig = String.format(PROMETHEUS_CONFIG_DEFAULT, scraping);
        if (config.forceScraping().orElse(scrapingRequired)) {
            boolean isTest = LaunchMode.current() == LaunchMode.TEST;
            Config runtimeConfig = ConfigProvider.getConfig();
            String rootPath = runtimeConfig.getOptionalValue("quarkus.management.root-path", String.class).orElse("/q");
            String metricsPath = runtimeConfig.getOptionalValue("quarkus.management.metrics.path", String.class)
                    .orElse("/metrics");
            String httpPortKey = isTest ? "quarkus.http.test-port" : "quarkus.http.port";
            Optional<Integer> optionalValue = runtimeConfig.getOptionalValue(httpPortKey, Integer.class);
            int httpPort = optionalValue.orElse(isTest ? 8081 : 8080); // when not set use default

            // On Linux, you can’t automatically resolve host.docker.internal,
            // you need to provide the following run flag when you start the container:

View on GitHub (pinned to e1c734241f)

Solutions

  1. Set the OTLP protocol to 'grpc' or 'http' exactly
  2. Trim/lowercase-check the config value (gRPC is matched case-insensitively, http is not)
  3. Remove conflicting OTEL protocol overrides so the default grpc is used

Example fix

// before
quarkus.observability.otel.protocol=http/protobuf
// after
quarkus.observability.otel.protocol=http
Defensive patterns

Strategy: validation

Validate before calling

String p = config.protocol();
if (!"grpc".equalsIgnoreCase(p) && !"http".equals(p)) throw new IllegalArgumentException("Unsupported OTEL protocol: " + p);

Try / catch

try { port = container.getPrivateOtlpPort(); } catch (IllegalArgumentException e) { port = ContainerConstants.OTEL_GRPC_EXPORTER_PORT; }

Prevention

When it happens

Trigger: quarkus.observability (or OTEL) protocol config set to an unrecognized value such as 'http/protobuf', 'https', a typo like 'grp', or empty string that is neither the gRPC nor HTTP constant.

Common situations: Copying OTEL exporter protocol values meant for the OTel SDK (e.g. 'http/protobuf') into the dev-service config; case/spacing typos; versions where only grpc and http are supported.

Related errors


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