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
- Give the configuration class a public no-arg constructor and standard setters matching schema field names
- Register a schema for the configuration class via DefaultSchema so the direct path is used
- Make the class and relevant setters public and non-abstract
- 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
- Annotate config classes with @DefaultSchema so the schema path is used
- Provide public no-arg constructors and setters matching schema field names
- Round-trip test: buildExternal then serialize/deserialize the config object
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
- Unrecognized value for stable unique names:
- Unable to find 'public static CoderProvider getCoderProvider
- Unable to invoke 'public static CoderProvider getCoderProvid
- Unable to generate coder for schema {schema}
- Unable to instantiate ExternalTransformBuilder from construc
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/36be67a8895087c3.
Report an issue: GitHub.