{"record":{"id":"5307a9436ea49049","repo":"apache/beam","slug":"expected-s-for-property-s-of-type-s-on-s","errorCode":null,"errorMessage":"Expected %s for property [%s] of type [%s] on [%s].","messagePattern":"Expected (.+?) for property \\[(.+?)\\] of type \\[(.+?)\\] on \\[(.+?)\\]\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/options/PipelineOptionsFactory.java","lineNumber":1471,"sourceCode":"                \"%n  - Setter for property [%s] should not be marked with @%s on %s\",\n                setter.descriptor.getName(),\n                annotationClass.getSimpleName(),\n                setter.settersWithTheAnnotationClassNames));\n      }\n      throw new IllegalArgumentException(builder.toString());\n    }\n  }\n\n  private static class MissingBeanMethod {\n    String methodType;\n    PropertyDescriptor property;\n  }\n\n  private static void throwForMissingBeanMethod(\n      Class<? extends PipelineOptions> iface, List<MissingBeanMethod> missingBeanMethods) {\n    if (missingBeanMethods.size() == 1) {\n      MissingBeanMethod missingBeanMethod = missingBeanMethods.get(0);\n      throw new IllegalArgumentException(\n          String.format(\n              \"Expected %s for property [%s] of type [%s] on [%s].\",\n              missingBeanMethod.methodType,\n              missingBeanMethod.property.getName(),\n              missingBeanMethod.property.getPropertyType().getName(),\n              iface.getName()));\n    } else if (missingBeanMethods.size() > 1) {\n      StringBuilder builder =\n          new StringBuilder(\n              String.format(\"Found missing property methods on [%s]:\", iface.getName()));\n      for (MissingBeanMethod method : missingBeanMethods) {\n        builder.append(\n            String.format(\n                \"%n  - Expected %s for property [%s] of type [%s]\",\n                method.methodType,\n                method.property.getName(),\n                method.property.getPropertyType().getName()));\n      }","sourceCodeStart":1453,"sourceCodeEnd":1489,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/options/PipelineOptionsFactory.java#L1453-L1489","documentation":"Thrown when a PipelineOptions interface declares one half of a bean property but not the other: e.g. a getter exists without a matching setter (or vice versa) of the required type. Beam's proxy needs both accessors (getters are mandatory; setters as applicable) to implement the property, so it reports exactly which bean method type, property name, property type, and interface are incomplete.","triggerScenarios":"PipelineOptionsFactory.fromArgs(...).as(iface.class) when throwForMissingBeanMethod finds a MissingBeanMethod: property 'foo' of type java.lang.String on iface has a getter but no 'void setFoo(String)' (or a setter without a getter).","commonSituations":"Adding a getter for a read-only-looking property and forgetting Beam requires setters for mutable options; renaming a setter's parameter type so it no longer matches the getter's property type; incomplete copy of an accessor pair.","solutions":["Add the missing bean method named in the message ('getter' or 'setter') with the exact property type given.","If the property type was changed, update the counterpart accessor to match it.","Remove the orphan accessor if the property is not actually needed."],"exampleFix":"// before\nString getFoo(); // no setter\n// after\nString getFoo();\nvoid setFoo(String value);","handlingStrategy":"validation","validationCode":"java.beans.Introspector.getBeanInfo(MyOptions.class).getPropertyDescriptors();\nfor (java.beans.PropertyDescriptor pd : java.beans.Introspector.getBeanInfo(MyOptions.class).getPropertyDescriptors()) {\n  boolean hasGet = pd.getReadMethod() != null, hasSet = pd.getWriteMethod() != null;\n  if (hasGet != hasSet) {\n    System.err.println(\"Property \" + pd.getName() + \" missing \" + (hasGet ? \"setter\" : \"getter\"));\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  PipelineOptionsFactory.fromArgs(args).as(MyOptions.class);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().startsWith(\"Expected getter\") || e.getMessage().startsWith(\"Expected setter\")) { /* add the missing accessor */ }\n  throw e;\n}","preventionTips":["Always generate getter and setter pairs together","When changing a property type, update both accessors in the same edit","Keep a unit test that calls PipelineOptionsFactory.as() on every options interface"],"tags":["java","apache-beam","pipeline-options","bean-property"],"backgroundTag":"missing-required-config-field","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"}