theonedev/onedev · error · IllegalStateException
Placeholder tag set on a component that renders its body onl
Error message
Placeholder tag set on a component that renders its body only. Component id: %s.
What it means
A component that renders only its body (no own tag) had setOutputMarkupPlaceholderTag / FLAG_PLACEHOLDER set, which cannot work without a tag to render the placeholder into. As with the markup-id case, behavior is governed by NotRenderableErrorStrategy: throw IllegalStateException or log a warning.
Source
Thrown at server-core/src/main/java/org/apache/wicket/Component.java:2608
}
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);
}
markupStream.next();
// Render the body only if open-body-close. Do not render if open-close.
if (tag.isOpen())
{
// Render the body. The default strategy will simply call the component's
// onComponentTagBody() implementation.
getMarkupSourcingStrategy().onComponentTagBody(this, markupStream, tag);
// Render close tagView on GitHub (pinned to d44925c47c)
Solutions
- Remove setOutputMarkupPlaceholderTag(true) for body-only components.
- Set renderBodyOnly(false) so the placeholder tag can be rendered.
- Relax NotRenderableErrorStrategy if the placeholder is irrelevant.
- Only apply placeholders to components intended for Ajax replacement.
- Audit base classes/helpers that bulk-enable output flags.
Example fix
// before field.setRenderBodyOnly(true); field.setOutputMarkupPlaceholderTag(true); // after field.setRenderBodyOnly(false); field.setOutputMarkupPlaceholderTag(true);
Defensive patterns
Strategy: validation
Validate before calling
if (component.isRenderBodyOnly() && component.getOutputMarkupPlaceholderTag()) { component.setOutputMarkupPlaceholderTag(false); } Type guard
boolean canHavePlaceholder(Component c) { return !c.isRenderBodyOnly(); } Try / catch
try { renderComponent(c); } catch (IllegalStateException e) { if (e.getMessage().contains("Placeholder tag")) { log.warn(e.getMessage()); } else { throw e; } } Prevention
- Apply setOutputMarkupPlaceholderTag only to components you Ajax-replace
- Avoid bulk flag-enable helpers over body-only components
- Render the component tag when a placeholder is required
When it happens
Trigger: Calling setOutputMarkupPlaceholderTag(true) on a component with renderBodyOnly=true, then rendering it; strict error strategy configured in Application's ExceptionSettings.
Common situations: Global Ajax-refresh setup code applying setOutputMarkupPlaceholderTag(true) to all children; inline fields/text fields configured body-only; strict strategy enabled for catching Ajax mistakes early.
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
- Markup id set on a component that renders its body only. Mar
- Placeholder tag set on a component that is usually not rende
- Pop state data is missing
- has not been properly detached. Something in the hierarchy
- has not been properly rendered. Something in the hierarchy
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/ea49d1c159b55e11.
Report an issue: GitHub.