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

  1. Fix getWrappedModel() to return the actual delegate model, never this.
  2. Ensure the inner model is created and passed into the wrapper's constructor.
  3. 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

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


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/3bc813ed2e193c7a. Report an issue: GitHub.