ObservationGrpcClientInterceptor throws NPE when NameResolver returns empty authority (original) (raw)
Description
When a custom gRPC NameResolver returns an empty string ("") for getServiceAuthority(), the ObservationGrpcClientInterceptor fails to handle this edge case properly, causing aNullPointerException during observation context creation.
Reproduction repository: https://github.com/GGGGGHT/grpc-uri-authority-reproduce
Environment
- Micrometer version: 1.15.0
- gRPC version: 1.63.0
- Java version: 25
Steps to Reproduce
- Create a gRPC channel with a custom
NameResolverthat returns empty string forgetServiceAuthority() - Configure
ObservationGrpcClientInterceptoron the channel - Make any gRPC call
Expected Behavior
The interceptor should handle empty authority gracefully without throwing an exception.
Actual Behavior
java.lang.NullPointerException
at java.base/java.util.Objects.requireNonNull(Objects.java:220)
at io.micrometer.common.ImmutableKeyValue.<init>(ImmutableKeyValue.java:38)
at io.micrometer.common.KeyValue.of(KeyValue.java:48)
at io.micrometer.common.KeyValue.of(KeyValue.java:58)
at io.micrometer.common.docs.KeyName.withValue(KeyName.java:46)
at io.micrometer.core.instrument.binder.grpc.DefaultGrpcClientObservationConvention.getLowCardinalityKeyValues(DefaultGrpcClientObservationConvention.java:51)
at io.micrometer.core.instrument.binder.grpc.DefaultGrpcClientObservationConvention.getLowCardinalityKeyValues(DefaultGrpcClientObservationConvention.java:29)
at io.micrometer.observation.SimpleObservation.stop(SimpleObservation.java:174)
at io.micrometer.core.instrument.binder.grpc.ObservationGrpcClientCall.handleFailure(ObservationGrpcClientCall.java:72)
at io.micrometer.core.instrument.binder.grpc.ObservationGrpcClientCall.start(ObservationGrpcClientCall.java:47)
Root Cause Chain
- NameResolver.getServiceAuthority() returns ""
- ObservationGrpcClientInterceptor.interceptCall() executes new URI(null, "", null, null, null) which throws URISyntaxException
- The exception is caught silently (lines 85-91 in ObservationGrpcClientInterceptor.java), leaving peerName as null
- DefaultGrpcClientObservationConvention.getLowCardinalityKeyValues() calls LowCardinalityKeyNames.PEER_NAME.withValue(context.getPeerName()) with null
- ImmutableKeyValue.requireNonNull(value) throws NPE
Suggested Fix
In DefaultGrpcClientObservationConvention.getLowCardinalityKeyValues(), add null check for context.getPeerName() before calling withValue():
KeyValue peerNameKeyValue = context.getPeerName() != null
? LowCardinalityKeyNames.PEER_NAME.withValue(context.getPeerName())
: LowCardinalityKeyNames.PEER_NAME.withValue("none");
Or provide a fallback value when peerName is null.
Additional Context
This issue is related to the gRPC observation interceptor, not the RPC method itself. When authority is empty, the URI construction fails and the peerName remains unset, which then causes the NPE when
building observation key-values.