apache/shenyu · error · ShenyuException

can not get defaultInstance Field of

Error message

can not get defaultInstance Field of %s

What it means

JsonServerServiceInterceptor.useMarshalledMessages wraps gRPC method descriptors for JSON transcoding. It needs the request message's default instance: first via a 'defaultInstanceField' reflection field, falling back to MethodDescriptor.PrototypeMarshaller.getMessagePrototype(). If neither is available, it cannot determine the request type and throws ShenyuException naming the marshaller class.

Solutions

  1. Use standard protobuf-generated marshallers (ProtoUtils.marshaller) for the service methods
  2. Ensure the marshaller's getMessagePrototype() returns a non-null prototype when implementing PrototypeMarshaller
  3. Upgrade/align grpc version so defaultInstance reflection works as expected
  4. Catch ShenyuException and fall back to native (non-json) gRPC proxying
Defensive patterns

Strategy: validation

Validate before calling

MethodDescriptor.PrototypeMarshaller<?> pm =
    marshaller instanceof MethodDescriptor.PrototypeMarshaller
        ? (MethodDescriptor.PrototypeMarshaller<?>) marshaller : null;
if (pm == null && ReflectUtils.getField(marshaller.getClass(), "defaultInstance") == null) {
    throw new IllegalStateException("marshaller exposes neither defaultInstance nor prototype");
}

Try / catch

try { interceptor.useJsonMessages(methodDescriptor); }
catch (ShenyuException e) { log.error("json mode unsupported for this marshaller", e); }

Prevention

When it happens

Trigger: Calling useJsonMessages on a MethodDescriptor whose request marshaller is neither a ProtoLiteUtils marshaller exposing a defaultInstance field nor a PrototypeMarshaller with a non-null message prototype (grpc 1.6.0-era compatibility path).

Common situations: Custom marshallers not generated by grpc's protoc plugin; very old or very new grpc versions where field names/behavior changed; services using hand-written Marshallers.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12). Data as JSON: /api/errors/328b54454653c5a8. Report an issue: GitHub.

Appendix: source

Thrown at shenyu-client/shenyu-client-grpc/src/main/java/org/apache/shenyu/client/grpc/json/JsonServerServiceInterceptor.java:89

     * @throws IllegalAccessException IllegalAccessException
     */
    public static <T> ServerServiceDefinition useMarshalledMessages(final ServerServiceDefinition serviceDef,
                                                                    final MethodDescriptor.Marshaller<T> marshaller)
            throws IllegalArgumentException, IllegalAccessException {
        List<ServerMethodDefinition<?, ?>> wrappedMethods = new ArrayList<>();
        List<MethodDescriptor<?, ?>> wrappedDescriptors = new ArrayList<>();

        // Wrap the descriptors
        for (final ServerMethodDefinition<?, ?> definition : serviceDef.getMethods()) {
            MethodDescriptor.Marshaller<?> requestMarshaller = definition.getMethodDescriptor().getRequestMarshaller();
            Field defaultInstanceField = ReflectUtils.getField(requestMarshaller.getClass(), "defaultInstance");
            Class<?> grpcRequestParamClass = null;
            if (Objects.isNull(defaultInstanceField)) {
                // Compatible with lower versions. eg: grpc 1.6.0
                if (requestMarshaller instanceof MethodDescriptor.PrototypeMarshaller) {
                    MethodDescriptor.PrototypeMarshaller<?> prototypeMarshaller = (PrototypeMarshaller<?>) requestMarshaller;
                    if (Objects.isNull(prototypeMarshaller.getMessagePrototype())) {
                        throw new ShenyuException(String.format("can not get defaultInstance Field of %s", requestMarshaller.getClass()));
                    }
                    grpcRequestParamClass = prototypeMarshaller.getMessagePrototype().getClass();
                }
            } else {
                defaultInstanceField.setAccessible(true);
                grpcRequestParamClass = defaultInstanceField.get(requestMarshaller).getClass();
            }

            String fullMethodName = definition.getMethodDescriptor().getFullMethodName();
            MethodDescriptor.MethodType methodType = definition.getMethodDescriptor().getType();
            METHOD_TYPE_MAP.put(fullMethodName, methodType);

            String[] splitMethodName = fullMethodName.split("/");
            fullMethodName = splitMethodName[0] + GrpcConstants.GRPC_JSON_SERVICE + "/" + splitMethodName[1];
            REQUEST_CLAZZ_MAP.put(fullMethodName, grpcRequestParamClass);

            final MethodDescriptor<?, ?> originalMethodDescriptor = definition.getMethodDescriptor();
            final MethodDescriptor<T, T> wrappedMethodDescriptor = originalMethodDescriptor

View on GitHub (pinned to 567142e072)