Quarkus Native Build Failure: Okhttp3/Interceptor Missing

by Alex Johnson 58 views

Experiencing a native build failure in your Quarkus application can be a frustrating roadblock. This article dives into a specific issue where the build breaks at startup due to the okhttp3/Interceptor class not being found. We'll explore the root cause, the context surrounding OpenTelemetry instrumentation, and potential solutions to get your Quarkus application up and running smoothly. If you're encountering a java.lang.NoClassDefFoundError: okhttp3/Interceptor during your Quarkus native build, you've come to the right place. Let's break down this problem and find a fix.

Understanding the Issue: Native Build Breaks with okhttp3/Interceptor Not Found

When you're working with Quarkus and aiming for optimal performance through native image compilation, you might encounter a perplexing error during the startup phase. This error often manifests as a java.lang.NoClassDefFoundError specifically targeting the okhttp3/Interceptor class. This typically happens when the application's runtime dependencies, particularly those related to networking and HTTP client interactions, are not correctly reflected in the native image. In simpler terms, the native image build process isn't picking up the necessary components of okhttp3, a popular HTTP client library, leading to a crash when the application tries to use it. This problem often arises in the context of tracing and monitoring tools, such as OpenTelemetry, which may rely on okhttp3 for exporting data. The error message, similar to the one below, is a clear indicator of this issue:

2025-11-25 11:57:51,098 ERROR [io.qua.run.Application] 
(Quarkus Main Thread) Failed to start application: java.lang.RuntimeException: Failed to start quarkus
        at io.quarkus.runner.ApplicationImpl.doStart(Unknown Source)
        ...
Caused by: java.lang.NoClassDefFoundError: okhttp3/Interceptor
        at io.opentelemetry.exporter.sender.okhttp.internal.OkHttpGrpcSenderProvider.createSender(OkHttpGrpcSenderProvider.java:45)
        ...

The stack trace pinpoints the okhttp3/Interceptor as the missing piece, suggesting that a component within your application or its dependencies is attempting to use okhttp3's interceptor functionality. This functionality is commonly used for adding custom logic to HTTP requests and responses, such as logging, authentication, or injecting headers. The challenge lies in ensuring that the native image build process is aware of this dependency and includes the necessary reflection configurations to make okhttp3 work correctly within the native image.

The Role of OpenTelemetry and Native Instrumentation

OpenTelemetry plays a crucial role in modern application observability, providing a standardized way to collect and export telemetry data like traces, metrics, and logs. In the context of Java applications, OpenTelemetry offers both automatic instrumentation and native instrumentation options. Automatic instrumentation relies on bytecode manipulation to inject tracing logic, while native instrumentation is directly integrated into libraries and frameworks. Quarkus, being a cloud-native framework, encourages the use of native instrumentation for performance and efficiency reasons. The excerpt from the OpenTelemetry documentation highlights this preference:

Native instrumentation is built directly into libraries or frameworks. OpenTelemetry encourages library authors to add native instrumentation using the API. In the long term, we hope the native instrumentation becomes the norm...

However, the issue arises when extensions or libraries within a Quarkus application rely on OpenTelemetry instrumentation that isn't fully native-compatible. In the case of the okhttp3/Interceptor error, the io.opentelemetry.instrumentation:opentelemetry-instrumentation-api-semconv dependency might be the culprit. This dependency, while providing semantic conventions for OpenTelemetry, might introduce dependencies like okhttp3 that are not automatically handled in the native image build process. This is where manual reflection configuration or alternative instrumentation approaches become necessary. It's important to understand that while Quarkus strives to provide seamless native image support, certain dependencies might require extra attention to ensure they function correctly in a native environment.

Digging Deeper: Why okhttp3 Might Be Excluded

To further complicate matters, Quarkus might explicitly exclude okhttp3 from certain dependencies, as seen in the provided pom.xml snippet:

<dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-exporter-otlp</artifactId>
    <exclusions>
        ...
        <exclusion>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
        </exclusion>
        <exclusion>
            <groupId>io.opentelemetry</groupId>
            <artifactId>opentelemetry-exporter-sender-okhttp</artifactId>
        </exclusion>
    </exclusions>
</dependency>

This exclusion suggests a deliberate decision to avoid okhttp3 in specific contexts, potentially due to compatibility issues or the availability of alternative HTTP client implementations within Quarkus. While this exclusion might be beneficial in some scenarios, it can lead to the NoClassDefFoundError if other parts of your application or its dependencies still expect okhttp3 to be present. The rationale behind such exclusions often involves optimizing the native image size and reducing the attack surface by removing unnecessary dependencies. However, it's crucial to carefully assess the impact of these exclusions on the overall functionality of your application, especially when dealing with third-party libraries or extensions that might have their own dependencies.

Reproducing the Bug: A Step-by-Step Guide

To effectively troubleshoot and resolve this issue, reproducing the bug consistently is essential. Here's a step-by-step guide based on the information provided:

  1. Use Quarkus 3.29.4: Ensure you're using the specified Quarkus version, as the behavior might differ in other versions due to dependency updates or bug fixes.
  2. Include quarkus-reactive-messaging-nats-jetstream 3.28.2: This extension seems to be a key component in triggering the issue, so make sure it's included in your project dependencies.
  3. Enable Tracing: Set the quarkus.otel.enabled property to true in your application.properties or application.yml file. This activates OpenTelemetry tracing, which often relies on HTTP client interactions and might expose the okhttp3 dependency.
  4. Perform a Native Build: Execute the native build process using the Quarkus Maven or Gradle plugin. This will create a native executable of your application.
  5. Run the Native Artifact: Execute the generated native executable. If the issue persists, you should encounter the NoClassDefFoundError during startup.

By following these steps, you can reliably reproduce the bug and start experimenting with potential solutions. The reproducibility of the issue is a crucial factor in determining whether a fix is effective and doesn't introduce any regressions.

Potential Solutions and Workarounds

Now that we understand the problem and how to reproduce it, let's explore some potential solutions and workarounds:

  1. Explicit Reflection Configuration: The most common solution for NoClassDefFoundError in native images is to provide explicit reflection configuration for the missing classes. This involves telling the native image builder to include metadata about okhttp3/Interceptor and its related classes. You can achieve this by creating a reflection-config.json file in your src/main/resources/META-INF/native-image directory. The content of this file would look something like this:
[
  {
    "name": "okhttp3.Interceptor",
    "allDeclaredConstructors": true,
    "allPublicMethods": true,
    "allDeclaredFields": true
  }
]

This configuration tells the native image builder to include reflection metadata for all constructors, public methods, and declared fields of the okhttp3.Interceptor class. You might need to add similar configurations for other related classes if the error persists. Remember to test thoroughly after adding reflection configurations, as excessive reflection can increase the native image size.

  1. Evaluate OpenTelemetry Dependencies: Examine the OpenTelemetry dependencies used in your project, particularly those related to exporters and instrumentation. If you're using dependencies like opentelemetry-exporter-sender-okhttp, consider alternatives that might be more native-friendly or rely on Quarkus' built-in HTTP client. Quarkus provides excellent support for RestEasy and Netty, which can be used for HTTP communication within your application and in OpenTelemetry exporters. If possible, switch to exporters that leverage these clients instead of okhttp3.

  2. Explore Native Instrumentation Options: Investigate whether native instrumentation is available for the specific components or libraries causing the issue. As highlighted earlier, native instrumentation is the preferred approach for OpenTelemetry in the long run. Check if Quarkus extensions or libraries you're using offer native instrumentation alternatives that avoid the need for okhttp3.

  3. Conditional Dependencies: If the okhttp3 dependency is only required in certain scenarios, consider using conditional dependencies. This involves including the dependency only when a specific feature is enabled or a particular environment is active. Quarkus provides mechanisms for defining conditional dependencies using profiles or build properties. This can help reduce the size of your native image and avoid unnecessary dependencies in situations where they're not needed.

  4. Report the Issue: If you've exhausted the above options and the issue persists, consider reporting it to the Quarkus community or the maintainers of the affected extension. Providing detailed information about your setup, including the Quarkus version, extensions used, and steps to reproduce the issue, can help them identify the root cause and implement a fix. Community contributions are crucial for improving the overall stability and native image compatibility of Quarkus.

Conclusion

Encountering a NoClassDefFoundError during a native build can be a challenging experience, but understanding the underlying causes and potential solutions is key to resolving the issue. In the case of the okhttp3/Interceptor error, the interaction between OpenTelemetry instrumentation and native image compilation plays a significant role. By providing explicit reflection configuration, evaluating OpenTelemetry dependencies, exploring native instrumentation options, and considering conditional dependencies, you can increase your chances of successfully building a native image of your Quarkus application. Remember to thoroughly test your application after implementing any changes to ensure that the fix doesn't introduce any regressions.

For further information on Quarkus native image builds and OpenTelemetry, refer to the official Quarkus documentation and OpenTelemetry resources. You can also find helpful discussions and solutions on the Quarkus community forum.