spring-projects/spring-framework · error · IllegalArgumentException
Write method must have exactly 1 or 2 parameters
Error message
Write method must have exactly 1 or 2 parameters: {method} What it means
Thrown as IllegalArgumentException by ExtendedBeanInfo when a non-void-returning method treated as a 'write method' (setter) has a parameter count that is neither 1 (simple setter) nor 2 (indexed setter). ExtendedBeanInfo inspects setter-like methods during construction and rejects ones that do not match JavaBeans conventions.
Solutions
- Rename or remove the offending setXxx method so it has exactly 1 (simple) or 2 (indexed, first int) parameters.
- Use a different method name prefix (e.g. withFoo) for fluent builders to avoid being treated as a setter.
- If the class is from a third party, avoid passing it through Spring's ExtendedBeanInfo; isolate it.
Example fix
// before
public void setItems(int i, String value, boolean flag) { ... }
// after - conform to indexed-setter convention or rename
public void setItem(int i, String value) { ... }
// or use a non-setter name
public Builder withItem(int i, String value) { ... } Defensive patterns
Strategy: validation
Validate before calling
// before exposing a class to ExtendedBeanInfo
for (Method m : cls.getMethods()) {
if (m.getName().startsWith("set") && m.getName().length() > 3) {
int n = m.getParameterCount();
if (n != 1 && n != 2) {
throw new IllegalStateException("non-conformant setter: " + m);
}
}
} Type guard
static boolean settersConform(Class<?> c) {
for (Method m : c.getMethods()) {
if (m.getName().startsWith("set") && m.getName().length() > 3) {
int n = m.getParameterCount();
if (n != 1 && n != 2) return false;
}
}
return true;
} Prevention
- Name fluent builder methods 'withXxx', not 'setXxx', to avoid setter detection.
- Keep simple setters to 1 param and indexed setters to 2 (first int).
- Add a unit test asserting no setXxx method has invalid arity for shared beans.
When it happens
Trigger: ExtendedBeanInfo is built over a BeanInfo; for each method it treats as a setter, if the parameter count is not 1 or 2 it throws. Typically triggered when a class has a method named setXxx with zero or 3+ parameters being picked up by the extended introspector.
Common situations: A class with an unconventional method like setFoo() with no args, setFoo(a, b, c), or a fluent builder setFoo(a, b) intended to be a setter but misinterpreted. Also seen with libraries that generate odd setter-shaped methods.
Related errors
- Bad indexed read method arg count
- Bad indexed write method arg count
- Bad read method arg count
- Bad write method arg count
- Indexed read method returns void
AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09).
Data as JSON: /api/errors/9328d84fb84d490b.
Report an issue: GitHub.
Appendix: source
Thrown at spring-beans/src/main/java/org/springframework/beans/ExtendedBeanInfo.java:184
existingPd.setWriteMethod(method);
}
}
else if (nParams == 2) {
if (existingPd == null) {
this.propertyDescriptors.add(
new SimpleIndexedPropertyDescriptor(propertyName, null, null, null, method));
}
else if (existingPd instanceof IndexedPropertyDescriptor indexedPd) {
indexedPd.setIndexedWriteMethod(method);
}
else {
this.propertyDescriptors.remove(existingPd);
this.propertyDescriptors.add(new SimpleIndexedPropertyDescriptor(
propertyName, existingPd.getReadMethod(), existingPd.getWriteMethod(), null, method));
}
}
else {
throw new IllegalArgumentException("Write method must have exactly 1 or 2 parameters: " + method);
}
}
private @Nullable PropertyDescriptor findExistingPropertyDescriptor(String propertyName, Class<?> propertyType) {
for (PropertyDescriptor pd : this.propertyDescriptors) {
final Class<?> candidateType;
final String candidateName = pd.getName();
if (pd instanceof IndexedPropertyDescriptor indexedPd) {
candidateType = indexedPd.getIndexedPropertyType();
if (candidateName.equals(propertyName) &&
(candidateType.equals(propertyType) || candidateType.equals(propertyType.componentType()))) {
return pd;
}
}
else {
candidateType = pd.getPropertyType();
if (candidateName.equals(propertyName) &&
(candidateType.equals(propertyType) || propertyType.equals(candidateType.componentType()))) {View on GitHub (pinned to 69bf83ad71)