apache/beam · error · java.lang.IllegalArgumentException

Failed to construct instance of configuration class '%s'

Error message

Failed to construct instance of configuration class '%s'

What it means

ExpansionService.payloadToConfig() builds an instance of the configuration class when its schema is not registered, using a setter-based reflective approach (payloadToConfigSetters); a ReflectiveOperationException there is rethrown as IllegalArgumentException with this message. It signals the config class could not be instantiated or populated reflectively.

Source

Thrown at sdks/java/expansion-service/src/main/java/org/apache/beam/sdk/expansion/service/ExpansionService.java:458

   * setters corresponding to each field in the row encoded by {@code payload}. Note {@link ConfigT}
   * may have additional setters not represented in the {@code payload} schema.
   *
   * <p>Exposed for testing only. No backwards compatibility guarantees.
   */
  @VisibleForTesting
  public static <ConfigT> ConfigT payloadToConfig(
      ExternalConfigurationPayload payload, Class<ConfigT> configurationClass) {
    try {
      return payloadToConfigSchema(payload, configurationClass);
    } catch (NoSuchSchemaException schemaException) {
      LOG.warn(
          "Configuration class '{}' has no schema registered. Attempting to construct with setter"
              + " approach.",
          configurationClass.getName());
      try {
        return payloadToConfigSetters(payload, configurationClass);
      } catch (ReflectiveOperationException e) {
        throw new IllegalArgumentException(
            String.format(
                "Failed to construct instance of configuration class '%s'",
                configurationClass.getName()),
            e);
      }
    }
  }

  private static <ConfigT> ConfigT payloadToConfigSchema(
      ExternalConfigurationPayload payload, Class<ConfigT> configurationClass)
      throws NoSuchSchemaException {
    Schema configSchema = SCHEMA_REGISTRY.getSchema(configurationClass);
    SerializableFunction<Row, ConfigT> fromRowFunc =
        SCHEMA_REGISTRY.getFromRowFunction(configurationClass);

    Row payloadRow = decodeConfigObjectRow(payload.getSchema(), payload.getPayload());

    if (!payloadRow.getSchema().assignableTo(configSchema)) {

View on GitHub (pinned to 12126d8942)

Solutions

  1. Give the configuration class a public no-arg constructor and standard setters matching schema field names
  2. Register a schema for the configuration class via DefaultSchema so the direct path is used
  3. Make the class and relevant setters public and non-abstract
  4. For immutable classes, register a schema with a creator method instead of relying on setters

Example fix

// before
public class MyConfig {
  private final String name;
  public MyConfig(String name) { this.name = name; } // no no-arg ctor, no setters
}
// after
@DefaultSchema(JavaBeanSchema.class)
public class MyConfig {
  private String name;
  public MyConfig() {}
  public String getName() { return name; }
  public void setName(String name) { this.name = name; }
}
Defensive patterns

Strategy: validation

Validate before calling

// ensure the class is reflectively constructible before relying on the setter path
Class<?> c = ConfigClass.class;
if (c.getConstructors() == null || java.util.Arrays.stream(c.getConstructors()).noneMatch(ctor -> ctor.getParameterCount() == 0)) throw new IllegalStateException("config class needs a no-arg constructor");

Try / catch

try { config = service.payloadToConfig(payload, ConfigClass.class); } catch (IllegalArgumentException e) { if (e.getMessage().contains("Failed to construct instance of configuration class")) { /* fix constructor/setters or register schema */ } throw e; }

Prevention

When it happens

Trigger: Calling payloadToConfig with a configuration class that lacks a registered schema and also lacks usable setters/no-arg constructor for the setter approach - missing default constructor, non-matching setter names/types, or inaccessible class.

Common situations: Custom POJO config classes without a public no-arg constructor; setters whose names don't match schema field names; config class not made public; Kotlin/data classes with immutable fields.

Related errors


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