theonedev/onedev · error · java.lang.IllegalStateException
Tried to remove validator that was not previously added. Mak
Error message
Tried to remove validator that was not previously added. Make sure your validator's equals() implementation is sufficient
What it means
FormComponent.remove(IValidator) throws IllegalStateException when no equal validator is currently registered on the component. Wicket locates the validator via equals(), so an unequal but 'logically same' validator cannot be removed.
Source
Thrown at server-core/src/main/java/org/apache/wicket/markup/html/form/FormComponent.java:575
break;
}
else if (behavior instanceof ValidatorAdapter)
{
if (((ValidatorAdapter<?>)behavior).getValidator().equals(validator))
{
match = behavior;
break;
}
}
}
if (match != null)
{
remove(match);
}
else
{
throw new IllegalStateException(
"Tried to remove validator that was not previously added. "
+ "Make sure your validator's equals() implementation is sufficient");
}
return this;
}
/**
* Adds a validator to this form component.
*
* @param validators
* The validator(s) to be added
* @return This
* @throws IllegalArgumentException
* if validator is null
* @see IValidator
*/
@SafeVarargs
public final FormComponent<T> add(final IValidator<? super T>... validators)View on GitHub (pinned to d44925c47c)
Solutions
- Keep a reference to the exact validator instance you added and remove that same instance
- Override equals() (and hashCode()) on custom validators so logically equal validators match
- Guard removal with a check, or add the validator once in onInitialize and toggle behavior another way
- Use component.getValidators() to confirm what is actually registered before removing
Example fix
// before form.add(new LengthValidator(5)); form.remove(new LengthValidator(5)); // different instance, no equals // after private final LengthValidator len = new LengthValidator(5); form.add(len); ... form.remove(len); // same instance
Defensive patterns
Strategy: validation
Validate before calling
if (formComponent.getValidators().stream().noneMatch(v -> v.equals(validator))) {
// do not call remove(validator)
} Try / catch
try {
formComponent.remove(validator);
} catch (IllegalStateException e) {
log.debug("Validator not present, skipping");
} Prevention
- Store and reuse the exact validator instance added
- Override equals()/hashCode() on custom validators
- Check getValidators() before removing
When it happens
Trigger: Calling formComponent.remove(validator) for a validator instance that was never added, was already removed, or whose equals() does not match the added instance (e.g. new instance each time without overriding equals).
Common situations: Creating a fresh validator object (e.g. new StringValidator(...)) and trying to remove it while the component holds a different instance; conditional add/remove logic where add was skipped; validators added in onInitialize but removal attempted before initialize.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Could not find Form parent for {this}
- FormComponent has to be required when the type is primitive
- Page classes should extend from BasePage.
- Base resource mapper should be used
- Invalid date range, expecting "yyyy-MM-dd to yyyy-MM-dd"
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/d95d049070c89fa5.
Report an issue: GitHub.