dotnet/aspnetcore · error · Error
The '${beforeElementSelector}' selector is not supported.
Error message
The '${beforeElementSelector}' selector is not supported. What it means
Thrown by attachRootComponentToElement when the elementSelector ends with '::before'. Blazor supports appending content '::after' a selector but does not support '::before' (CSS pseudo-elements are not real DOM nodes you can prepend into), so it is explicitly rejected.
Source
Thrown at src/Components/Web.JS/src/Rendering/Renderer.ts:43
let browserRenderer = browserRenderers[browserRendererId];
if (!browserRenderer) {
browserRenderer = new BrowserRenderer(browserRendererId);
browserRenderers[browserRendererId] = browserRenderer;
}
browserRenderer.attachRootComponentToLogicalElement(componentId, logicalElement, appendContent);
}
export function attachRootComponentToElement(elementSelector: string, componentId: number, browserRendererId: number): void {
const afterElementSelector = '::after';
const beforeElementSelector = '::before';
let appendContent = false;
if (elementSelector.endsWith(afterElementSelector)) {
elementSelector = elementSelector.slice(0, -afterElementSelector.length);
appendContent = true;
} else if (elementSelector.endsWith(beforeElementSelector)) {
throw new Error(`The '${beforeElementSelector}' selector is not supported.`);
}
const element = getAndRemovePendingRootComponentContainer(elementSelector)
|| document.querySelector(elementSelector);
if (!element) {
throw new Error(`Could not find any element matching selector '${elementSelector}'.`);
}
// 'allowExistingContents' to keep any prerendered content until we do the first client-side render
// Only client-side Blazor supplies a browser renderer ID
attachRootComponentToLogicalElement(browserRendererId, toLogicalElement(element, /* allow existing contents */ true), componentId, appendContent);
}
export function getRendererer(browserRendererId: number): BrowserRenderer | undefined {
return browserRenderers[browserRendererId];
}
export function renderBatch(browserRendererId: number, batch: RenderBatch): void {View on GitHub (pinned to 294cab2f9b)
Solutions
- Use a real container element and append/prepend via your own DOM manipulation instead of '::before'.
- Use '::after' (supported) when you only need to append.
- Restructure markup so the insertion point is an actual element rather than a pseudo-element.
Defensive patterns
Strategy: validation
Validate before calling
// Reject '::before' selectors before attach.
function assertSelector(s: string) {
if (s.endsWith('::before')) throw new Error("'::before' is not supported; use a real container");
} Prevention
- Never use '::before' as an attach target; pseudo-elements aren't DOM nodes.
- Use '::after' (supported) or a real container element for prepend needs.
- Restructure markup to expose a real insertion-point element.
When it happens
Trigger: Server attaching a root component with a selector suffixed '::before' (e.g. via component descriptor or RegisterForJavaScript with a prepend target).
Common situations: Assuming symmetric '::after'/'::before' support; copy-paste of an '::after' selector pattern with '::before'; older docs/tutorials implying prepend is supported.
Related errors
- Could not find any element matching selector '${elementSelec
- Invalid sequence number or identifier '${sequenceOrIdentifie
- Could not resolve a root component with SSR component ID '${
- initialParameters must be an object, even if empty.
- Dynamic root components have already been enabled.
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/31328c14c3122ab3.
Report an issue: GitHub.