apache/flink · error · UnsupportedOperationException

Expected two fields for the map (key/value), but got: {}

Error message

Expected two fields for the map (key/value), but got: {}

What it means

When building a writer for a protobuf map field, the nested message type must have exactly two fields (key and value) per protobuf's map encoding. Any other field count throws UnsupportedOperationException from createMapWriter.

Source

Thrown at flink-formats/flink-parquet/src/main/java/org/apache/flink/formats/parquet/protobuf/PatchedProtoWriteSupport.java:432

                                @Override
                                public Optional<GroupType> visit(
                                        LogicalTypeAnnotation.MapLogicalTypeAnnotation
                                                mapLogicalType) {
                                    return ofNullable(
                                            type.asGroupType()
                                                    .getType("key_value")
                                                    .asGroupType()
                                                    .getType("value")
                                                    .asGroupType());
                                }
                            })
                    .orElse(type.asGroupType());
        }

        private MapWriter createMapWriter(FieldDescriptor fieldDescriptor, Type type) {
            List<FieldDescriptor> fields = fieldDescriptor.getMessageType().getFields();
            if (fields.size() != 2) {
                throw new UnsupportedOperationException(
                        "Expected two fields for the map (key/value), but got: " + fields);
            }

            // KeyFieldWriter
            FieldDescriptor keyProtoField = fields.get(0);
            FieldWriter keyWriter = createWriter(keyProtoField, type);
            keyWriter.setFieldName(keyProtoField.getName());
            keyWriter.setIndex(0);

            // ValueFieldWriter
            FieldDescriptor valueProtoField = fields.get(1);
            FieldWriter valueWriter = createWriter(valueProtoField, type);
            valueWriter.setFieldName(valueProtoField.getName());
            valueWriter.setIndex(1);

            return new MapWriter(keyWriter, valueWriter);
        }

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Define the field as a proper proto map: map<K,V> field = N; so the compiler generates the 2-field MapEntry
  2. If using a hand-built Descriptor for a map-like structure, ensure the entry message has exactly key and value fields
  3. For repeated key-value groups that are not maps, use repeated message instead of map semantics

Example fix

// before (hand-built descriptor entry with 3 fields)
// message BadEntry { string key = 1; string value = 2; string extra = 3; }

// after
// message GoodEntry { string key = 1; string value = 2; }
// or in proto: map<string, string> entries = 1;
Defensive patterns

Strategy: validation

Validate before calling

FieldDescriptor fd = ...;
if (fd.isMapField() && fd.getMessageType().getFields().size() != 2) { throw new IllegalArgumentException("map entry must have exactly key+value: " + fd.getFullName()); }

Prevention

When it happens

Trigger: A .proto map field whose entry message somehow has != 2 fields - typically hand-constructed Descriptors, proto schema manipulation, or a map-like repeated group message passed where a true map is expected.

Common situations: Custom Descriptor construction, dynamic descriptors built at runtime, or protobuf editions/features producing unexpected map entry shapes.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/be3bafe8e1dccf6c. Report an issue: GitHub.