apache/shenyu · error · RuntimeException
dynamic build JsonMarshaller descriptor is fail
Error message
dynamic build JsonMarshaller descriptor is fail
What it means
JsonMessage.jsonDescriptor builds a protobuf FileDescriptor at runtime from a generated FileDescriptorProto for the JSON message type. If Descriptors.FileDescriptor.buildFrom throws DescriptorValidationException, the dynamically constructed descriptor is invalid, and the code logs the cause and rethrows a RuntimeException with this message. This typically means the embedded proto definition is malformed or inconsistent.
Solutions
- Read the logged DescriptorValidationException message (the 'Caused by' in the stack trace) to identify the exact invalid element, then fix the descriptor/proto resource.
- Use a consistent, unmodified shenyu-protocol-grpc artifact; restore the original JSON descriptor proto resources if they were customized.
- Align the protobuf-java runtime version with the one the descriptors were generated for.
- Clear stale build artifacts and rebuild shenyu-protocol-grpc so descriptor resources regenerate cleanly.
Defensive patterns
Strategy: try-catch
Try / catch
try {
return jsonDescriptor();
} catch (RuntimeException e) {
if ("dynamic build JsonMarshaller descriptor is fail".equals(e.getMessage())) {
LOG.error("descriptor build failed; check protobuf resources/version", e.getCause());
}
throw e;
} Prevention
- Pin protobuf-java runtime to the version the descriptors were generated with.
- Never hand-edit bundled descriptor proto resources.
- Log DescriptorValidationException details to catch schema drift early in CI.
When it happens
Trigger: Calling JsonMessage.jsonDescriptor()/buildJsonMarshallerDescriptor when the FileDescriptorProto for GrpcConstants.JSON_DESCRIPTOR_PROTO_NAME fails validation — e.g. dependency type references not resolvable, duplicate type names, or a corrupted/modified proto descriptor resource.
Common situations: Mismatches between the shenyu-protocol-grpc version and the proto assets it bundles; custom builds where JSON_DESCRIPTOR_PROTO resources were modified; protobuf-java runtime version incompatibilities with descriptor features used in the generated proto.
Related errors
- build json response message is error, newBuilder method is…
- Unable to merge from the supplied input stream
- Unable to merge from the supplied input stream
- grpc client must config the contextPath, ipAndPort
- can not get defaultInstance Field of
AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12).
Data as JSON: /api/errors/31035cb4ce01b864.
Report an issue: GitHub.
Appendix: source
Thrown at shenyu-protocol/shenyu-protocol-grpc/src/main/java/org/apache/shenyu/protocol/grpc/message/JsonMessage.java:77
DescriptorProtos.DescriptorProto.Builder jsonMarshaller = DescriptorProtos.DescriptorProto.newBuilder();
jsonMarshaller.setName(GrpcConstants.JSON_DESCRIPTOR_PROTO_NAME);
jsonMarshaller.addFieldBuilder()
.setName(GrpcConstants.JSON_DESCRIPTOR_PROTO_FIELD_NAME)
.setNumber(1)
.setType(DescriptorProtos.FieldDescriptorProto.Type.TYPE_STRING);
// build File Descriptor Proto
DescriptorProtos.FileDescriptorProto.Builder fileDescriptorProtoBuilder = DescriptorProtos.FileDescriptorProto.newBuilder();
fileDescriptorProtoBuilder.addMessageType(jsonMarshaller);
DescriptorProtos.FileDescriptorProto fileDescriptorProto = fileDescriptorProtoBuilder.build();
try {
Descriptors.FileDescriptor fileDescriptor = Descriptors.FileDescriptor
.buildFrom(fileDescriptorProto, new Descriptors.FileDescriptor[0]);
return fileDescriptor.findMessageTypeByName(GrpcConstants.JSON_DESCRIPTOR_PROTO_NAME);
} catch (Descriptors.DescriptorValidationException e) {
LOG.error("dynamic build JsonMarshaller descriptor is fail: {}", e.getMessage());
throw new RuntimeException("dynamic build JsonMarshaller descriptor is fail", e);
}
}
/**
* buildJsonMessage.
*
* @param jsonParamMap jsonParamMap
* @return DynamicMessageList
*/
public static List<DynamicMessage> buildJsonMessageList(final Map<String, Object> jsonParamMap) {
ParamCheckUtils.checkParamsLength(jsonParamMap.size(), GrpcConstants.JSON_DESCRIPTOR_PROTO_FIELD_NUM);
JsonArray jsonParams = (JsonArray) jsonParamMap.get(GrpcConstants.JSON_DESCRIPTOR_PROTO_FIELD_NAME);
List<DynamicMessage> jsonMessageList = new ArrayList<>(jsonParams.size());
jsonParams.forEach(jsonParam -> {
DynamicMessage jsonMessage = buildJsonMessage(GsonUtils.getInstance().toJson(jsonParam));
jsonMessageList.add(jsonMessage);
});
View on GitHub (pinned to 567142e072)