{"record":{"id":"36be67a8895087c3","repo":"apache/beam","slug":"failed-to-construct-instance-of-configuration-class-s","errorCode":null,"errorMessage":"Failed to construct instance of configuration class '%s'","messagePattern":"Failed to construct instance of configuration class '(.+?)'","errorType":"exception","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/expansion-service/src/main/java/org/apache/beam/sdk/expansion/service/ExpansionService.java","lineNumber":458,"sourceCode":"   * setters corresponding to each field in the row encoded by {@code payload}. Note {@link ConfigT}\n   * may have additional setters not represented in the {@code payload} schema.\n   *\n   * <p>Exposed for testing only. No backwards compatibility guarantees.\n   */\n  @VisibleForTesting\n  public static <ConfigT> ConfigT payloadToConfig(\n      ExternalConfigurationPayload payload, Class<ConfigT> configurationClass) {\n    try {\n      return payloadToConfigSchema(payload, configurationClass);\n    } catch (NoSuchSchemaException schemaException) {\n      LOG.warn(\n          \"Configuration class '{}' has no schema registered. Attempting to construct with setter\"\n              + \" approach.\",\n          configurationClass.getName());\n      try {\n        return payloadToConfigSetters(payload, configurationClass);\n      } catch (ReflectiveOperationException e) {\n        throw new IllegalArgumentException(\n            String.format(\n                \"Failed to construct instance of configuration class '%s'\",\n                configurationClass.getName()),\n            e);\n      }\n    }\n  }\n\n  private static <ConfigT> ConfigT payloadToConfigSchema(\n      ExternalConfigurationPayload payload, Class<ConfigT> configurationClass)\n      throws NoSuchSchemaException {\n    Schema configSchema = SCHEMA_REGISTRY.getSchema(configurationClass);\n    SerializableFunction<Row, ConfigT> fromRowFunc =\n        SCHEMA_REGISTRY.getFromRowFunction(configurationClass);\n\n    Row payloadRow = decodeConfigObjectRow(payload.getSchema(), payload.getPayload());\n\n    if (!payloadRow.getSchema().assignableTo(configSchema)) {","sourceCodeStart":440,"sourceCodeEnd":476,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/expansion-service/src/main/java/org/apache/beam/sdk/expansion/service/ExpansionService.java#L440-L476","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\npublic class MyConfig {\n  private final String name;\n  public MyConfig(String name) { this.name = name; } // no no-arg ctor, no setters\n}\n// after\n@DefaultSchema(JavaBeanSchema.class)\npublic class MyConfig {\n  private String name;\n  public MyConfig() {}\n  public String getName() { return name; }\n  public void setName(String name) { this.name = name; }\n}","handlingStrategy":"validation","validationCode":"// ensure the class is reflectively constructible before relying on the setter path\nClass<?> c = ConfigClass.class;\nif (c.getConstructors() == null || java.util.Arrays.stream(c.getConstructors()).noneMatch(ctor -> ctor.getParameterCount() == 0)) throw new IllegalStateException(\"config class needs a no-arg constructor\");","typeGuard":null,"tryCatchPattern":"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; }","preventionTips":["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"],"tags":["java","beam","expansion-service","reflection","configuration"],"backgroundTag":"invalid-constructor-argument","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}