theonedev/onedev · error · IllegalStateException

Markup id set on a component that renders its body only. Mar

Error message

Markup id set on a component that renders its body only. Markup id: %s, component id: %s.

What it means

A component that renders only its body (not its own tag) was flagged with setOutputMarkupId(true), which is meaningless and likely a mistake because there is no tag to attach the id to. Depending on ExceptionSettings.NotRenderableErrorStrategy, Wicket either throws IllegalStateException or logs a warning.

Source

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

		try
		{
			// Render open tag
			boolean renderBodyOnly = getRenderBodyOnly();
			if (renderBodyOnly)
			{
				ExceptionSettings.NotRenderableErrorStrategy notRenderableErrorStrategy = ExceptionSettings.NotRenderableErrorStrategy.LOG_WARNING;
				if (Application.exists())
				{
					notRenderableErrorStrategy = getApplication().getExceptionSettings().getNotRenderableErrorStrategy();
				}

				if (getFlag(FLAG_OUTPUT_MARKUP_ID))
				{
					String message = String.format("Markup id set on a component that renders its body only. " +
					                               "Markup id: %s, component id: %s.", getMarkupId(), getId());
					if (notRenderableErrorStrategy == ExceptionSettings.NotRenderableErrorStrategy.THROW_EXCEPTION)
					{
						throw new IllegalStateException(message);
					}
					log.warn(message);
				}
				if (getFlag(FLAG_PLACEHOLDER))
				{
					String message = String.format("Placeholder tag set on a component that renders its body only. " +
					                               "Component id: %s.", getId());
					if (notRenderableErrorStrategy == ExceptionSettings.NotRenderableErrorStrategy.THROW_EXCEPTION)
					{
						throw new IllegalStateException(message);
					}
					log.warn(message);
				}
			}
			else
			{
				renderComponentTag(tag);
			}

View on GitHub (pinned to d44925c47c)

Solutions

  1. Don't call setOutputMarkupId(true) on render-body-only components; render their tag instead (setRenderBodyOnly(false)).
  2. If Ajax-updating is needed, allow the tag to render so an id exists.
  3. Change NotRenderableErrorStrategy to LOG_ERROR/WARN if the warning is acceptable.
  4. Guard: `if (!c.isRenderBodyOnly()) c.setOutputMarkupId(true);`.
  5. Or setOutputMarkupPlaceholderTag(true) if you need a tag placeholder for Ajax.

Example fix

// before
label.setRenderBodyOnly(true);
label.setOutputMarkupId(true); // body-only: no tag for the id
// after
label.setRenderBodyOnly(false);
label.setOutputMarkupId(true); // tag now rendered with the markup id
Defensive patterns

Strategy: validation

Validate before calling

if (component.isRenderBodyOnly() && component.getFlag(Component.FLAG_OUTPUT_MARKUP_ID)) { log.warn("outputMarkupId on body-only component " + component.getId()); }

Type guard

boolean canHaveMarkupId(Component c) { return !c.isRenderBodyOnly() || c.getOutputMarkupPlaceholderTag(); }

Try / catch

try { renderComponent(c); } catch (IllegalStateException e) { if (e.getMessage().contains("renders its body only")) { log.warn(e.getMessage()); } else { throw e; } }

Prevention

When it happens

Trigger: Calling setOutputMarkupId(true) on components whose renderBodyOnly flag is set (or whose markup is set to not render the tag), then rendering; configuring NotRenderableErrorStrategy.THROW_EXCEPTION makes this fatal.

Common situations: Setting outputMarkupId globally for Ajax updates while some components are render-body-only; using InlinePanel/transparent containers with outputMarkupId; strategy configured to THROW_EXCEPTION in Application.init for strictness.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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