{"record":{"id":"c3ee3101b5a91919","repo":"apache/druid","slug":"invalid-value-type","errorCode":null,"errorMessage":"Invalid Value type.","messagePattern":"Invalid Value type\\.","errorType":"exception","errorClass":"InvalidProtocolBufferException","httpStatus":null,"severity":"error","filePath":"extensions-core/protobuf-extensions/src/main/java/org/apache/druid/data/input/protobuf/ProtobufConverter.java","lineNumber":218,"sourceCode":"        msg -> {\n          final Descriptors.Descriptor descriptor = msg.getDescriptorForType();\n          final Descriptors.FieldDescriptor field = descriptor.findFieldByName(\"fields\");\n          if (field == null) {\n            throw new InvalidProtocolBufferException(\"Invalid Struct type.\");\n          }\n          // Struct is formatted as a map object.\n          return convertSingleValue(field, msg.getField(field));\n        }\n    );\n    converters.put(\n        Value.getDescriptor().getFullName(),\n        msg -> {\n          final Map<Descriptors.FieldDescriptor, Object> fields = msg.getAllFields();\n          if (fields.isEmpty()) {\n            return null;\n          }\n          if (fields.size() != 1) {\n            throw new InvalidProtocolBufferException(\"Invalid Value type.\");\n          }\n          final Map.Entry<Descriptors.FieldDescriptor, Object> entry = fields.entrySet().stream().findFirst().get();\n          return convertSingleValue(entry.getKey(), entry.getValue());\n        }\n    );\n    converters.put(\n        ListValue.getDescriptor().getFullName(),\n        msg -> {\n          Descriptors.Descriptor descriptor = msg.getDescriptorForType();\n          Descriptors.FieldDescriptor field = descriptor.findFieldByName(\"values\");\n          if (field == null) {\n            throw new InvalidProtocolBufferException(\"Invalid ListValue type.\");\n          }\n          return convertList(field, (List<?>) msg.getField(field));\n        }\n    );\n    return converters;\n  }","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/protobuf-extensions/src/main/java/org/apache/druid/data/input/protobuf/ProtobufConverter.java#L200-L236","documentation":"google.protobuf.Value is a oneof that must have exactly one kind set (null_value, number_value, string_value, bool_value, struct_value, list_value). Druid's converter converts a Value message to a single value; when the message has more than one field populated it is malformed, so this InvalidProtocolBufferException is thrown.","triggerScenarios":"A google.protobuf.Value message with two or more simultaneously-set oneof members is passed to ProtobufConverter.convertMessage (e.g. bytes crafted by hand or produced by a non-conformant producer); fields.size() > 1 at conversion time.","commonSituations":"Hand-crafted or fuzzed protobuf bytes; a buggy producer writing multiple oneof fields; binary data truncated/corrupted in transit causing malformed parse results.","solutions":["Fix the producer to set exactly one field of the Value oneof","Validate upstream bytes with protoc --decode before ingesting","Check for data corruption in the transport (Kafka topic, network) that could merge or corrupt records"],"exampleFix":"// before: producer sets two members of the Value oneof\nvalue.setStringValue(\"x\"); value.setBoolValue(true);\n// after: set exactly one\nvalue.setStringValue(\"x\");","handlingStrategy":"try-catch","validationCode":"Message valueMsg = ...;\nif (\"google.protobuf.Value\".equals(valueMsg.getDescriptorForType().getFullName())\n    && valueMsg.getAllFields().size() > 1) {\n  throw new IllegalStateException(\"google.protobuf.Value has multiple oneof members set\");\n}","typeGuard":"boolean isValidValue(Message msg) {\n  if (!\"google.protobuf.Value\".equals(msg.getDescriptorForType().getFullName())) return true;\n  int n = msg.getAllFields().size();\n  return n == 0 || n == 1;\n}","tryCatchPattern":"try {\n  Map<String, Object> row = ProtobufConverter.convertMessage(msg);\n} catch (ParseException e) {\n  log.error(\"Malformed Value oneof in record; fix producer or skip record\", e);\n  // route to DLQ instead of failing the whole read\n}","preventionTips":["In producers, always set exactly one member of the Value oneof","Add a producer-side unit test that round-trips messages through JsonFormat","Monitor transport for byte corruption (checksums, Kafka ISR health)"],"tags":["protobuf","deserialization","malformed-data"],"backgroundTag":"protobuf-unmarshal-failed","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}