theonedev/onedev · error · WicketRuntimeException
Model for
Error message
Model for
What it means
While unwrapping IWrapModel chains, Wicket detects a model whose getWrappedModel() returns itself, i.e. an infinite self-reference, and throws WicketRuntimeException 'Model for ... is self-referential'. This guard prevents StackOverflowError and infinite loops when resolving the innermost model.
Source
Thrown at server-core/src/main/java/org/apache/wicket/Component.java:3794
return (requestFlags & flag) != 0;
}
/**
* Finds the innermost IModel object for an IModel that might contain nested IModel(s).
*
* @param model
* The model
* @return The innermost (most nested) model
*/
protected final IModel<?> getInnermostModel(final IModel<?> model)
{
IModel<?> nested = model;
while (nested != null && nested instanceof IWrapModel)
{
final IModel<?> next = ((IWrapModel<?>)nested).getWrappedModel();
if (nested == next)
{
throw new WicketRuntimeException("Model for " + nested + " is self-referential");
}
nested = next;
}
return nested;
}
/**
* Gets the component's current model comparator. Implementations can be used for testing the
* current value of the components model data with the new value that is given.
*
* @return the value defaultModelComparator
*/
public IModelComparator getModelComparator()
{
return defaultModelComparator;
}
/**View on GitHub (pinned to d44925c47c)
Solutions
- Fix getWrappedModel() to return the actual delegate model, never this.
- Ensure the inner model is created and passed into the wrapper's constructor.
- Add an assertion/unit test that repeatedly unwrapping terminates.
Example fix
// before
class MyWrapModel implements IWrapModel<String> {
public IModel<?> getWrappedModel() { return this; } // bug
}
// after
class MyWrapModel implements IWrapModel<String> {
private final IModel<String> inner;
MyWrapModel(IModel<String> inner) { this.inner = inner; }
public IModel<?> getWrappedModel() { return inner; }
} Defensive patterns
Strategy: validation
Validate before calling
IModel<?> m = wrapper;
int depth = 0;
while (m instanceof IWrapModel) {
if (++depth > 100) throw new IllegalStateException("self-referential model");
m = ((IWrapModel<?>) m).getWrappedModel();
} Try / catch
try { resolveInnermostModel(model); } catch (WicketRuntimeException e) { log.error("self-referential model: {}", e.getMessage()); } Prevention
- In IWrapModel implementations, never return this from getWrappedModel().
- Store the delegate model in a final field assigned in the constructor.
- Unit test unwrap termination for custom wrapper models.
When it happens
Trigger: Implementing IWrapModel and returning `this` from getWrappedModel(); a wrapper model accidentally wiring itself as its own wrapped model during construction or configuration.
Common situations: Custom component-property-wrapping models where the constructor passes itself instead of the delegate; copy/paste mistakes in wrapper implementations; forms with wrapped models (IComponentInheritedModel) implemented incorrectly.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Attempt to set a model object on a component without a model
- Page classes should extend from BasePage.
- Base resource mapper should be used
- Invalid date range, expecting "yyyy-MM-dd to yyyy-MM-dd"
- Path '${mountPath}' should be mounted to a svg sprite resour
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/3bc813ed2e193c7a.
Report an issue: GitHub.