{"record":{"id":"2528be97b0649cae","repo":"apache/flink","slug":"protocol-buffers-editions-syntax-is-not-supported","errorCode":null,"errorMessage":"Protocol Buffers editions syntax is not supported","messagePattern":"Protocol Buffers editions syntax is not supported","errorType":"validation","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"flink-formats/flink-parquet/src/main/java/org/apache/flink/formats/parquet/protobuf/PatchedProtoWriteSupport.java","lineNumber":481,"sourceCode":"\n        /** Used for writing nonrepeated (optional, required) fields. */\n        @Override\n        final void writeField(Object value) {\n            recordConsumer.startField(fieldName, index);\n            writeRawValue(value);\n            recordConsumer.endField(fieldName, index);\n        }\n\n        private void writeAllFields(MessageOrBuilder pb) {\n            Descriptor messageDescriptor = pb.getDescriptorForType();\n            // ============================================================================\n            // BEGIN PATCH: Replace enum-based syntax detection with string-based approach\n            // ============================================================================\n            String syntax = messageDescriptor.getFile().toProto().getSyntax();\n\n            // Check for editions syntax (not supported)\n            if (\"editions\".equals(syntax)) {\n                throw new UnsupportedOperationException(\n                        \"Protocol Buffers editions syntax is not supported\");\n            }\n\n            // proto2 uses empty string or \"proto2\", proto3 uses \"proto3\"\n            boolean isProto2 = syntax.isEmpty() || \"proto2\".equals(syntax);\n\n            if (isProto2) {\n                // ============================================================================\n                // END PATCH\n                // ============================================================================\n                // Returns changed fields with values. Map is ordered by id.\n                Map<FieldDescriptor, Object> changedPbFields = pb.getAllFields();\n\n                for (Map.Entry<FieldDescriptor, Object> entry : changedPbFields.entrySet()) {\n                    FieldDescriptor fieldDescriptor = entry.getKey();\n\n                    if (fieldDescriptor.isExtension()) {\n                        // Field index of an extension field might overlap with a base field.","sourceCodeStart":463,"sourceCodeEnd":499,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-formats/flink-parquet/src/main/java/org/apache/flink/formats/parquet/protobuf/PatchedProtoWriteSupport.java#L463-L499","documentation":"The patched protobuf-to-parquet writer detects the file's syntax via string comparison and rejects 'editions' syntax. Protobuf editions change semantics in ways this writer's proto2/proto3 field-presence logic cannot handle, so it throws UnsupportedOperationException.","triggerScenarios":"Writing a Message whose .proto file declares 'edition = \"2023\"' (or later) instead of syntax = \"proto2\"/\"proto3\".","commonSituations":"Upgrading a proto file to editions 2023, or depending on a third-party .proto that uses editions, then feeding those messages to ProtoParquetOutputFormat.","solutions":["Convert the .proto back to syntax = \"proto3\" (or proto2) and regenerate the Java classes","Keep a separate proto2/proto3 build of the message classes for the parquet sink path","Watch upstream parquet-proto support for editions and upgrade once supported"],"exampleFix":"// before\n// edition = \"2023\";\n// message User { string name = 1; }\n\n// after\nsyntax = \"proto3\";\nmessage User { string name = 1; }","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"boolean isEditionsSyntax(MessageOrBuilder msg) {\n  return \"editions\".equals(msg.getDescriptorForType().getFile().toProto().getSyntax());\n}","tryCatchPattern":"try { writer.write(msg); } catch (UnsupportedOperationException e) { if (e.getMessage().contains(\"editions\")) { // regenerate protos with proto3 syntax and retry } throw e; }","preventionTips":["Keep protos fed to the parquet sink on syntax proto2/proto3","Add a build-time check rejecting 'edition =' in protos used for parquet output","Track parquet-proto upstream for editions support before upgrading proto files"],"tags":["parquet","protobuf","editions","compatibility"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}