apache/beam · error · IllegalArgumentException
Found incorrectly annotated property methods, if a method is
Error message
Found incorrectly annotated property methods, if a method is annotated with either @JsonSerialize or @JsonDeserialize then it must be annotated with both.%n - Property [%s] had only @%s
What it means
PipelineOptions validation found a getter method annotated with exactly one of @JsonSerialize or @JsonDeserialize. Beam requires both annotations together so serialization and deserialization behavior stay symmetric; a one-sided annotation is considered a programming error in the PipelineOptions interface.
Source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/options/PipelineOptionsFactory.java:1523
StringBuilder builder =
new StringBuilder(
"Found incorrectly annotated property methods, if a method is annotated with either @JsonSerialize or @JsonDeserialize then it must be annotated with both.");
for (InconsistentJsonSerializeAndDeserializeAnnotation annotation : inconsistentAnnotations) {
String presentAnnotation;
if (annotation.hasJsonDeserializeAttribute) {
presentAnnotation = "JsonDeserialize";
} else {
presentAnnotation = "JsonSerialize";
}
builder.append(
String.format(
"%n - Property [%s] had only @%s",
annotation.property.getName(), presentAnnotation));
}
throw new IllegalArgumentException(builder.toString());
}
/** A {@link Comparator} that uses the classes name to compare them. */
private static class ClassNameComparator implements Comparator<Class<?>> {
static final ClassNameComparator INSTANCE = new ClassNameComparator();
@Override
public int compare(Class<?> o1, Class<?> o2) {
return o1.getName().compareTo(o2.getName());
}
}
/** A {@link Comparator} that uses the generic method signature to sort them. */
private static class MethodComparator implements Comparator<Method> {
static final MethodComparator INSTANCE = new MethodComparator();
@Override
public int compare(Method o1, Method o2) {View on GitHub (pinned to 12126d8942)
Solutions
- Add the missing counterpart annotation to the getter so both @JsonSerialize and @JsonDeserialize are present
- If only one direction is needed, remove the single annotation entirely and rely on default Jackson behavior
Example fix
// before @JsonSerialize(using = MySerializer.class) MyValue getMyOption(); // after @JsonSerialize(using = MySerializer.class) @JsonDeserialize(using = MyDeserializer.class) MyValue getMyOption();
Defensive patterns
Strategy: validation
Validate before calling
for (Method m : MyOptions.class.getMethods()) {
boolean s = m.isAnnotationPresent(JsonSerialize.class);
boolean d = m.isAnnotationPresent(JsonDeserialize.class);
if (s != d) throw new IllegalStateException(m.getName() + " needs both @JsonSerialize and @JsonDeserialize");
} Try / catch
try { PipelineOptionsFactory.as(MyOptions.class); } catch (IllegalArgumentException e) { /* inspect annotation pair error */ } Prevention
- Always add both annotations as a pair when customizing Jackson behavior
- Add an ArchUnit or annotation-checking unit test over your options interfaces
When it happens
Trigger: Declaring a PipelineOptions interface method with only @JsonSerialize (without @JsonDeserialize) or only @JsonDeserialize (without @JsonSerialize), then calling PipelineOptionsFactory.create()/as()/fromArgs() which triggers property annotation validation.
Common situations: Adding custom Jackson (de)serialization to a value-typed option and forgetting the matching counterpart annotation; copying an annotation from an example without both.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Failed to read PipelineOptions from JSON
- Property [%s] is marked with contradictory annotations. Foun
- 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/1f409abb9cd22c35.
Report an issue: GitHub.