theonedev/onedev · error · IllegalStateException

Cannot remove

Error message

Cannot remove 

What it means

Component.remove() removes the component from its parent, and throws IllegalStateException when the component has no parent (parent == null). Wicket cannot detach a component that was never added to a parent container or was already removed. The message includes the component's toString() to identify the orphan.

Source

Thrown at server-core/src/main/java/org/apache/wicket/Component.java:2321

	 */
	public final void redirectToInterceptPage(final Page page)
	{
		throw new RestartResponseAtInterceptPageException(page);
	}

	/**
	 * Removes this component from its parent. It's important to remember that a component that is
	 * removed cannot be referenced from the markup still.
	 * <p>
	 * You must not use this method in your callback to any of the
	 * {@link MarkupContainer#visitChildren(IVisitor)} methods. See <a
	 * href="https://issues.apache.org/jira/browse/WICKET-3229">WICKET-3329</a>.
	 */
	public final void remove()
	{
		if (parent == null)
		{
			throw new IllegalStateException("Cannot remove " + this + " from null parent!");
		}
		parent.remove(this);
	}


	/**
	 * Render the Component.
	 */
	public final void render()
	{
		HierarchicalContext.push(new HierarchicalContext(new ComponentHierarchical(this)));
		try {
			RuntimeException exception = null;
	
			try
			{
				// Invoke prepareForRender only if this is the root component to be rendered
				MarkupContainer parent = getParent();

View on GitHub (pinned to d44925c47c)

Solutions

  1. Guard with `if (component.getParent() != null) component.remove();`.
  2. Track whether you added the component yourself before removing it.
  3. Use `component.getParent().remove(component)` only after verifying parent exists.
  4. Replace visibility control with setVisible(false) instead of add/remove churn.
  5. Check for double-removal paths in event handlers.

Example fix

// before
submitButton.remove();
// after
if (submitButton.getParent() != null) {
    submitButton.remove();
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (component.getParent() == null) { log.warn("skip remove; not attached"); return; }

Type guard

boolean canRemove(Component c) { return c.getParent() != null; }

Try / catch

try { component.remove(); } catch (IllegalStateException e) { log.warn("component already detached", e); }

Prevention

When it happens

Trigger: Calling component.remove() on a component that was never added via container.add(component), or on one that was already removed (e.g. double remove, remove inside a loop that also removes via parent), or on a root Page-level component detached during serialization.

Common situations: Calling remove() in onDetach/onAfterRender when the component was conditionally not added; removing a component twice from event handlers; calling remove() on components obtained from an iterator while the parent removes them.

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


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