apache/beam · error · IllegalArgumentException
Property [%s] is marked with contradictory annotations. Foun
Error message
Property [%s] is marked with contradictory annotations. Found [%s].
What it means
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.
Source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/options/PipelineOptionsFactory.java:1141
final AnnotationPredicates annotationPredicates) {
List<InconsistentlyAnnotatedGetters> inconsistentlyAnnotatedGetters = new ArrayList<>();
for (final PropertyDescriptor descriptor : descriptors) {
if (descriptor.getReadMethod() == null
|| IGNORED_METHODS.contains(descriptor.getReadMethod())) {
continue;
}
SortedSet<Method> getters = methodNameToAllMethodMap.get(descriptor.getReadMethod());
SortedSet<Method> gettersWithTheAnnotation =
Sets.filter(getters, annotationPredicates.forMethod);
Set<Annotation> distinctAnnotations =
gettersWithTheAnnotation.stream()
.flatMap(method -> Arrays.stream(method.getAnnotations()))
.filter(annotationPredicates.forAnnotation)
.collect(Collectors.toSet());
if (distinctAnnotations.size() > 1) {
throw new IllegalArgumentException(
String.format(
"Property [%s] is marked with contradictory annotations. Found [%s].",
descriptor.getName(),
gettersWithTheAnnotation.stream()
.flatMap(
method ->
Arrays.stream(method.getAnnotations())
.filter(annotationPredicates.forAnnotation)
.map(
annotation ->
String.format(
"[%s on %s]",
ReflectHelpers.formatAnnotation(annotation),
ReflectHelpers.formatMethodWithClass(method))))
.collect(Collectors.joining(", "))));
}
Iterable<String> getterClassNames =View on GitHub (pinned to 12126d8942)
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.
Example fix
// before
interface MyOptions extends PipelineOptions {
@Default.String("a")
String getFoo();
}
interface OtherOptions extends PipelineOptions {
@Hidden
String getFoo();
}
// after
interface MyOptions extends PipelineOptions {
@Default.String("a")
String getFoo();
} Defensive patterns
Strategy: validation
Validate before calling
for (java.lang.reflect.Method m : MyOptions.class.getMethods()) {
java.util.Set<Class<?>> anns = new java.util.HashSet<>();
for (java.lang.annotation.Annotation a : m.getAnnotations()) anns.add(a.annotationType());
if (m.getName().startsWith("get") && anns.size() > 1) {
throw new IllegalStateException("Property " + m.getName() + " has multiple property annotations: " + anns);
}
} Try / catch
try {
PipelineOptions options = PipelineOptionsFactory.fromArgs(args).as(MyOptions.class);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("contradictory annotations")) { /* fix interface annotations */ }
throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- Expected getter for property [%s] to be marked with @%s on a
- Property getters are inconsistently marked with @%s:
- All inherited interfaces of [%s] should inherit from the Pip
- Method [%s] has multiple definitions %s with different retur
- Interface [%s] has Methods with multiple definitions with di
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/959f5f8cf4eb7dea.
Report an issue: GitHub.