{"record":{"id":"959f5f8cf4eb7dea","repo":"apache/beam","slug":"property-s-is-marked-with-contradictory-annotations-found-s","errorCode":null,"errorMessage":"Property [%s] is marked with contradictory annotations. Found [%s].","messagePattern":"Property \\[(.+?)\\] is marked with contradictory annotations\\. Found \\[(.+?)\\]\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/options/PipelineOptionsFactory.java","lineNumber":1141,"sourceCode":"      final AnnotationPredicates annotationPredicates) {\n    List<InconsistentlyAnnotatedGetters> inconsistentlyAnnotatedGetters = new ArrayList<>();\n    for (final PropertyDescriptor descriptor : descriptors) {\n      if (descriptor.getReadMethod() == null\n          || IGNORED_METHODS.contains(descriptor.getReadMethod())) {\n        continue;\n      }\n\n      SortedSet<Method> getters = methodNameToAllMethodMap.get(descriptor.getReadMethod());\n      SortedSet<Method> gettersWithTheAnnotation =\n          Sets.filter(getters, annotationPredicates.forMethod);\n      Set<Annotation> distinctAnnotations =\n          gettersWithTheAnnotation.stream()\n              .flatMap(method -> Arrays.stream(method.getAnnotations()))\n              .filter(annotationPredicates.forAnnotation)\n              .collect(Collectors.toSet());\n\n      if (distinctAnnotations.size() > 1) {\n        throw new IllegalArgumentException(\n            String.format(\n                \"Property [%s] is marked with contradictory annotations. Found [%s].\",\n                descriptor.getName(),\n                gettersWithTheAnnotation.stream()\n                    .flatMap(\n                        method ->\n                            Arrays.stream(method.getAnnotations())\n                                .filter(annotationPredicates.forAnnotation)\n                                .map(\n                                    annotation ->\n                                        String.format(\n                                            \"[%s on %s]\",\n                                            ReflectHelpers.formatAnnotation(annotation),\n                                            ReflectHelpers.formatMethodWithClass(method))))\n                    .collect(Collectors.joining(\", \"))));\n      }\n\n      Iterable<String> getterClassNames =","sourceCodeStart":1123,"sourceCodeEnd":1159,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/options/PipelineOptionsFactory.java#L1123-L1159","documentation":"Thrown by PipelineOptionsFactory when a single property getter/setter group on a PipelineOptions interface carries two different property annotations (e.g. both @Description annotations conflicting markers such as @Default and @Hidden via distinct annotation predicates) that cannot all apply simultaneously. Beam validates annotation consistency while building the options class and refuses to create an options object with contradictory metadata.","triggerScenarios":"Calling PipelineOptionsFactory.fromArgs(...).as(SomeOptions.class) (or .create()) where the distinctAnnotations set built from all getters of one property has size > 1, i.e. the same property is marked with mutually exclusive annotations across the interface hierarchy.","commonSituations":"A property getter is annotated in one sub-interface and re-annotated differently in another sub-interface that both feed the final options interface; copy-pasting a getter and editing its annotations while leaving both methods registered; merging option interfaces during a refactor.","solutions":["Find the property named in the message and inspect all getters/setters for it across the interface hierarchy (including inherited interfaces).","Remove or unify the contradictory annotations so each property carries exactly one consistent set.","If both behaviors are needed, split them into two separate properties instead of one.","Rebuild and rerun; the factory caches validation so re-run fromArgs/create after the fix."],"exampleFix":"// before\ninterface MyOptions extends PipelineOptions {\n  @Default.String(\"a\")\n  String getFoo();\n}\ninterface OtherOptions extends PipelineOptions {\n  @Hidden\n  String getFoo();\n}\n// after\ninterface MyOptions extends PipelineOptions {\n  @Default.String(\"a\")\n  String getFoo();\n}","handlingStrategy":"validation","validationCode":"for (java.lang.reflect.Method m : MyOptions.class.getMethods()) {\n  java.util.Set<Class<?>> anns = new java.util.HashSet<>();\n  for (java.lang.annotation.Annotation a : m.getAnnotations()) anns.add(a.annotationType());\n  if (m.getName().startsWith(\"get\") && anns.size() > 1) {\n    throw new IllegalStateException(\"Property \" + m.getName() + \" has multiple property annotations: \" + anns);\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  PipelineOptions options = PipelineOptionsFactory.fromArgs(args).as(MyOptions.class);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"contradictory annotations\")) { /* fix interface annotations */ }\n  throw e;\n}","preventionTips":["Keep each property's annotations on exactly one declaration in the hierarchy","Prefer inheriting getters instead of re-declaring them in sub-interfaces","Validate all options interfaces in a unit test at build time"],"tags":["java","apache-beam","pipeline-options","annotation-validation"],"backgroundTag":"conflicting-config-options","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"}