{"record":{"id":"3a15a1dd888a5661","repo":"apache/druid","slug":"protobuf-message-could-not-be-parsed-3a15a1","errorCode":null,"errorMessage":"Protobuf message could not be parsed","messagePattern":"Protobuf message could not be parsed","errorType":"exception","errorClass":"ParseException","httpStatus":null,"severity":"error","filePath":"extensions-core/protobuf-extensions/src/main/java/org/apache/druid/data/input/protobuf/ProtobufReader.java","lineNumber":103,"sourceCode":"    final Map<String, Object> record;\n    final Map<String, Object> plainJava = convertMessage(intermediateRow);\n    record = recordFlattener.flatten(plainJava);\n    return Collections.singletonList(MapInputRowParser.parse(inputRowSchema, record));\n  }\n\n  @Override\n  protected List<Map<String, Object>> toMap(DynamicMessage intermediateRow)\n  {\n    return Collections.singletonList(convertMessage(intermediateRow));\n  }\n\n  private static Map<String, Object> convertMessage(Message msg)\n  {\n    try {\n      return ProtobufConverter.convertMessage(msg);\n    }\n    catch (InvalidProtocolBufferException e) {\n      throw new ParseException(null, e, \"Protobuf message could not be parsed\");\n    }\n  }\n}\n","sourceCodeStart":85,"sourceCodeEnd":107,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/protobuf-extensions/src/main/java/org/apache/druid/data/input/protobuf/ProtobufReader.java#L85-L107","documentation":"ProtobufReader.convertMessage delegates record conversion to ProtobufConverter.convertMessage, which can throw InvalidProtocolBufferException when well-known types are malformed (e.g. invalid Value/Struct/wrapper shapes). The reader wraps that failure in a ParseException with this message, aborting conversion of that record.","triggerScenarios":"Any record whose message tree contains a well-known type the specialized converters reject (Value with >1 oneof set, descriptors missing 'value'/'fields'/'values'), or a JsonFormat print failure for Any, encountered while reading rows via plainJava or toMap.","commonSituations":"Malformed records produced upstream; mixed protobuf runtime versions in extensions; hand-written bytes or a corrupt Kafka message.","solutions":["Inspect the offending record and decode it standalone with protoc to find the malformed well-known type","Fix the producer so Value oneofs set exactly one field and wrappers/Struct/ListValue follow the standard layout","Align protobuf-java versions across Druid extensions to eliminate descriptor mismatches"],"exampleFix":"// before: producer writes two Value oneof members\nbuilder.setNumberValue(1.0); builder.setStringValue(\"x\");\n// after: exactly one\nbuilder.setNumberValue(1.0);","handlingStrategy":"try-catch","validationCode":"// pre-validate a sample record before wiring ingestion\nMessage sample = DynamicMessage.parseFrom(descriptor, sampleBytes);\nMap<String, Object> row = ProtobufConverter.convertMessage(sample); // throws early if malformed","typeGuard":"boolean isConvertible(Message msg) {\n  try {\n    ProtobufConverter.convertMessage(msg);\n    return true;\n  } catch (InvalidProtocolBufferException e) {\n    return false;\n  }\n}","tryCatchPattern":"try {\n  Map<String, Object> row = reader.toMap(record);\n} catch (ParseException e) {\n  log.error(\"Record failed protobuf conversion; send to DLQ\", e);\n  deadLetterQueue.send(record, e);\n}","preventionTips":["Fix producers to emit conformant well-known types (one Value oneof member, standard wrappers)","Keep protobuf-java versions aligned across producer and Druid","Decode failing records with protoc --decode_raw to diagnose before changing config"],"tags":["protobuf","deserialization","record-parsing"],"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"}