apache/beam · error · UnsupportedOperationException

Unsupported field type

Error message

Unsupported field type: %s

What it means

ProtoBeamConverter.createProtoToBeamConverter() builds a converter mapping a proto FieldDescriptor's type to a Beam/Java type. Its switch over FieldType has no case for the encountered field type, so it throws UnsupportedOperationException with the raw type name. The proto schema contains a field type the converter does not support.

Solutions

  1. Change the proto schema to use only field types supported by ProtoBeamConverter (standard scalars, strings, bytes, messages, maps, enums).
  2. Upgrade the Beam SDK so the converter covers newer protobuf field types.
  3. Implement a custom converter for the unsupported field instead of the generic proto-to-Beam path.
  4. Check Descriptors.FieldDescriptor.getType() of the offending field to identify what needs replacing.

Example fix

// before
optional MyGroup group_field = 1; // group type unsupported
// after
message MyGroup { ... }
MyGroup group_field = 1; // regular message field
Defensive patterns

Strategy: try-catch

Validate before calling

for (Descriptors.FieldDescriptor f : descriptor.getFields()) {
  switch (f.getType()) {
    case GROUP: throw new IllegalStateException("unsupported field type " + f.getType() + " in " + f.getFullName());
    default: break;
  }
}

Type guard

static boolean isSupportedFieldType(Descriptors.FieldDescriptor f) {
  switch (f.getType()) {
    case GROUP: return false; // extend as needed for unsupported types
    default: return true;
  }
}

Try / catch

try {
  converter = ProtoBeamConverter.createProtoToBeamConverter(fieldDescriptor);
} catch (UnsupportedOperationException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("Unsupported field type")) {
    throw new IllegalStateException("Replace or upgrade field: " + e.getMessage(), e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Converting a proto message whose schema uses a field type not handled by the switch (e.g. newer well-known types, group-type fields, or unsupported scalars) via elementConverter/keyConverter/valueConverter paths.

Common situations: Protos compiled with a newer protobuf version introducing types unknown to the Beam converter; using group/oneof wrapper fields; schemas using enums nested in maps where the enum path falls through to default.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/ad6e0d0957cbd0d2. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/extensions/protobuf/src/main/java/org/apache/beam/sdk/extensions/protobuf/ProtoBeamConverter.java:162

              Descriptors.Descriptor timestampDescriptor = message.getDescriptorForType();
              Descriptors.FieldDescriptor secondsFieldDescriptor =
                  timestampDescriptor.findFieldByNumber(1);
              Descriptors.FieldDescriptor nanosFieldDescriptor =
                  timestampDescriptor.findFieldByNumber(2);
              long seconds = (long) message.getField(secondsFieldDescriptor);
              int nanos = (int) message.getField(nanosFieldDescriptor);
              return Instant.ofEpochSecond(seconds, nanos);
            };
          case EnumerationType.IDENTIFIER:
            EnumerationType enumerationType = fieldType.getLogicalType(EnumerationType.class);
            return enumValue ->
                enumerationType.toInputType(
                    ((Descriptors.EnumValueDescriptor) enumValue).getNumber());
          default:
            throw new UnsupportedOperationException();
        }
      default:
        throw new UnsupportedOperationException(
            "Unsupported field type: " + fieldType.getTypeName());
    }
  }

  static BeamToProtoConverter<Object, Object> createBeamToProtoConverter(
      Descriptors.FieldDescriptor fieldDescriptor) {
    if (fieldDescriptor.isRepeated()) {
      if (fieldDescriptor.isMapField()) {
        Descriptors.Descriptor mapDescriptor = fieldDescriptor.getMessageType();
        Descriptors.FieldDescriptor keyDescriptor = mapDescriptor.findFieldByNumber(1);
        Descriptors.FieldDescriptor valueDescriptor = mapDescriptor.findFieldByNumber(2);
        BeamToProtoConverter<Object, Object> keyToProto =
            createBeamToProtoSingularConverter(keyDescriptor);
        BeamToProtoConverter<Object, Object> valueToProto =
            createBeamToProtoSingularConverter(valueDescriptor);
        return map -> {
          ImmutableList.Builder<Message> protoList = ImmutableList.builder();
          ((Map<Object, Object>) map)

View on GitHub (pinned to 12126d8942)