apache/beam · error · java.lang.IllegalArgumentException

Given message schema

Error message

Given message schema: '%s'%ndoes not match schema inferred from protobuf class.%nProtobuf class: '%s'%nInferred schema: '%s'

What it means

ProtoPayloadSerializerProvider verifies that the schema supplied by the caller (requiredSchema) is assignable from the schema inferred from the protobuf class. If they diverge, it throws this IllegalArgumentException showing both schemas, preventing silently wrong serialization of rows to proto bytes.

Solutions

  1. Regenerate/refresh the required schema from the current .proto definition so both sides match.
  2. Align field names and types between the table schema and the proto message.
  3. Print/compare the inferred schema in the message against requiredSchema and fix mismatches.
  4. Ensure the same protoClass is used to infer the schema as is configured.

Example fix

// before
Schema required = Schema.of(Field.of("id", FieldType.STRING)); // proto id is INT64
// after
Schema required = Schema.of(Field.of("id", FieldType.INT64));
Defensive patterns

Strategy: validation

Validate before calling

Schema inferred = new ProtoMessageSchema().schemaFor(TypeDescriptor.of(protoClass));
if (!inferred.assignableTo(requiredSchema)) {
  throw new IllegalArgumentException("schema drift for " + protoClass.getName());
}

Try / catch

try { serializer = provider.getSerializer(params); } catch (IllegalArgumentException e) { log.error("schema mismatch: {}", e.getMessage()); throw e; }

Prevention

When it happens

Trigger: Calling getSerializer with a table schema that doesn't match the schema ProtoMessageSchema infers from the protoClass — e.g. fields added/removed/renamed in the .proto file or the table schema, type changes (int64 vs string), or the .proto was regenerated after the schema was defined.

Common situations: Proto definition updated (new field, changed type) but stored schema/config not updated; hand-written schema with a typo; using a different protoClass than the one the schema was built for.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at sdks/java/extensions/protobuf/src/main/java/org/apache/beam/sdk/extensions/protobuf/ProtoPayloadSerializerProvider.java:59

  }

  private static Class<? extends Message> getClass(Map<String, Object> tableParams) {
    String protoClassName = checkArgumentNotNull(tableParams.get("protoClass")).toString();
    try {
      Class<?> protoClass = Class.forName(protoClassName);
      return protoClass.asSubclass(Message.class);
    } catch (ClassNotFoundException e) {
      throw new IllegalArgumentException("Incorrect proto class provided: " + protoClassName, e);
    }
  }

  private static <T extends Message> void inferAndVerifySchema(
      Class<T> protoClass, Schema requiredSchema) {
    @Nonnull
    Schema inferredSchema =
        checkArgumentNotNull(new ProtoMessageSchema().schemaFor(TypeDescriptor.of(protoClass)));
    if (!inferredSchema.assignableTo(requiredSchema)) {
      throw new IllegalArgumentException(
          String.format(
              "Given message schema: '%s'%n"
                  + "does not match schema inferred from protobuf class.%n"
                  + "Protobuf class: '%s'%n"
                  + "Inferred schema: '%s'",
              requiredSchema, protoClass.getName(), inferredSchema));
    }
  }

  @Override
  public PayloadSerializer getSerializer(Schema schema, Map<String, Object> tableParams) {
    Class<? extends Message> protoClass = getClass(tableParams);
    inferAndVerifySchema(protoClass, schema);
    SimpleFunction<byte[], Row> toRowFn = ProtoMessageSchema.getProtoBytesToRowFn(protoClass);
    return PayloadSerializer.of(
        ProtoMessageSchema.getRowToProtoBytesFn(protoClass),
        bytes -> {
          Row rawRow = toRowFn.apply(bytes);

View on GitHub (pinned to 12126d8942)