{"record":{"id":"f349eeaab34598a1","repo":"apache/beam","slug":"the-configuration-class-s-is-missing-a-setter-s-for-s-with","errorCode":null,"errorMessage":"The configuration class %s is missing a setter %s for %s with type %s","messagePattern":"The configuration class (.+?) is missing a setter (.+?) for (.+?) with type (.+?)","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":512,"sourceCode":"\n    ConfigT config = constructor.newInstance();\n    for (Field field : configRow.getSchema().getFields()) {\n      String key = field.getName();\n      @Nullable Object value = configRow.getValue(field.getName());\n\n      String fieldName = key;\n\n      Coder coder = SchemaCoder.coderForFieldType(field.getType());\n      Class type = coder.getEncodedTypeDescriptor().getRawType();\n\n      String setterName =\n          \"set\" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);\n      Method method;\n      try {\n        // retrieve the setter for this field\n        method = config.getClass().getMethod(setterName, type);\n      } catch (NoSuchMethodException e) {\n        throw new IllegalArgumentException(\n            String.format(\n                \"The configuration class %s is missing a setter %s for %s with type %s\",\n                config.getClass(),\n                setterName,\n                fieldName,\n                coder.getEncodedTypeDescriptor().getType().getTypeName()),\n            e);\n      }\n      invokeSetter(config, value, method);\n    }\n    return config;\n  }\n\n  // Checker framework is conservative for Method#invoke, args are NonNull\n  // See https://checkerframework.org/manual/#reflection-resolution\n  @SuppressWarnings(\"nullness\")\n  private static <ConfigT> void invokeSetter(ConfigT config, @Nullable Object value, Method method)\n      throws IllegalAccessException, InvocationTargetException {","sourceCodeStart":494,"sourceCodeEnd":530,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/expansion-service/src/main/java/org/apache/beam/sdk/expansion/service/ExpansionService.java#L494-L530","documentation":"Thrown by ExpansionService.payloadToConfigSetters when reflective lookup of a setter method on the configuration class fails. For each schema field the service computes the JavaBean setter name ('set' + capitalized field name) and calls getClass().getMethod(setterName, type); if no such public setter exists the mapping from Row to config object cannot proceed.","triggerScenarios":"Expanding a transform whose configuration class lacks a public setter matching a schema field — e.g. field 'numShards' requires setNumShards(int) but the class only has a builder, a final field, or a setter with a different parameter type.","commonSituations":"Config class written with immutable/builder style instead of JavaBean getters+setters; schema field name doesn't match the Java property naming convention; setter exists but takes a boxed/primitive type different from the coder's encoded type.","solutions":["Add the missing public setter to the configuration class, named set<Field> with exactly the type shown in the message.","Rename the schema field (or add a SchemaCreate/SchemaFieldGetterAndSetter compatible accessor) so it matches an existing setter.","Verify the field's type in the schema matches the setter's parameter type (e.g. int vs long vs String)."],"exampleFix":"// before\nclass MyConfig { public final String pattern; MyConfig(String p) { pattern = p; } }\n// after\nclass MyConfig {\n  private String pattern;\n  public String getPattern() { return pattern; }\n  public void setPattern(String pattern) { this.pattern = pattern; }\n}","handlingStrategy":"validation","validationCode":"for (Schema.Field f : schema.getFields()) {\n  String setter = \"set\" + Character.toUpperCase(f.getName().charAt(0)) + f.getName().substring(1);\n  if (Arrays.stream(MyConfig.class.getMethods()).noneMatch(m -> m.getName().equals(setter) && m.getParameterCount() == 1)) {\n    throw new IllegalStateException(\"Missing setter: \" + setter);\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  Row configRow = /* decode payload */;\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"is missing a setter\")) { /* fix config class accessors */ }\n  throw e;\n}","preventionTips":["Always implement JavaBean-style getters and setters on expansion configuration classes.","Keep schema field names aligned with Java property naming conventions.","Add a unit test that round-trips the config class through Row encode/decode."],"tags":["java","beam","reflection","javabeans"],"backgroundTag":"method-not-implemented","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}