apache/beam · error · java.lang.IllegalArgumentException

Incorrect proto class provided

Error message

Incorrect proto class provided: ${protoClassName}

What it means

ProtoPayloadSerializerProvider reads a 'protoClass' parameter naming a protobuf Message subclass; if Class.forName cannot load that class, it throws this IllegalArgumentException wrapping the ClassNotFoundException.

Solutions

  1. Correct the fully-qualified class name in the protoClass parameter.
  2. Ensure the jar containing the generated proto class is on the classpath and staged to workers.
  3. Use Class.forName locally in a startup check to validate the name early.
  4. If the class was renamed/moved, update the configuration.

Example fix

// before
"protoClass": "com.example.MyProoto$MyMsg"
// after
"protoClass": "com.example.MyProto$MyMsg"
Defensive patterns

Strategy: validation

Validate before calling

try {
  Class.forName(protoClassName).asSubclass(com.google.protobuf.Message.class);
} catch (ClassNotFoundException e) {
  throw new IllegalArgumentException("protoClass not on classpath: " + protoClassName);
}

Try / catch

try { serializer = provider.getSerializer(params); } catch (IllegalArgumentException e) { log.error("bad protoClass config: {}", e.getMessage()); }

Prevention

When it happens

Trigger: Configuring a table/serializer with params {"protoClass": "com.example.MyProto"} where the class name is misspelled, the class is not on the classpath, or the jar containing generated protos is missing from the worker.

Common situations: Typo or wrong package in config; fat jar not bundling the generated proto classes; class present in dev but not staged to runners (Dataflow/Spark/Flink workers); refactoring moved/renamed the proto class.

Related errors


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

Appendix: source

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

import org.apache.beam.sdk.transforms.SimpleFunction;
import org.apache.beam.sdk.values.Row;
import org.apache.beam.sdk.values.TypeDescriptor;

@Internal
@AutoService(PayloadSerializerProvider.class)
public class ProtoPayloadSerializerProvider implements PayloadSerializerProvider {
  @Override
  public String identifier() {
    return "proto";
  }

  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));
    }
  }

View on GitHub (pinned to 12126d8942)