{"record":{"id":"31328c14c3122ab3","repo":"dotnet/aspnetcore","slug":"the-beforeelementselector-selector-is-not-sup","errorCode":null,"errorMessage":"The '${beforeElementSelector}' selector is not supported.","messagePattern":"The '(.+?)' selector is not supported\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/Components/Web.JS/src/Rendering/Renderer.ts","lineNumber":43,"sourceCode":"  let browserRenderer = browserRenderers[browserRendererId];\n  if (!browserRenderer) {\n    browserRenderer = new BrowserRenderer(browserRendererId);\n    browserRenderers[browserRendererId] = browserRenderer;\n  }\n\n  browserRenderer.attachRootComponentToLogicalElement(componentId, logicalElement, appendContent);\n}\n\nexport function attachRootComponentToElement(elementSelector: string, componentId: number, browserRendererId: number): void {\n  const afterElementSelector = '::after';\n  const beforeElementSelector = '::before';\n  let appendContent = false;\n\n  if (elementSelector.endsWith(afterElementSelector)) {\n    elementSelector = elementSelector.slice(0, -afterElementSelector.length);\n    appendContent = true;\n  } else if (elementSelector.endsWith(beforeElementSelector)) {\n    throw new Error(`The '${beforeElementSelector}' selector is not supported.`);\n  }\n\n  const element = getAndRemovePendingRootComponentContainer(elementSelector)\n    || document.querySelector(elementSelector);\n  if (!element) {\n    throw new Error(`Could not find any element matching selector '${elementSelector}'.`);\n  }\n\n  // 'allowExistingContents' to keep any prerendered content until we do the first client-side render\n  // Only client-side Blazor supplies a browser renderer ID\n  attachRootComponentToLogicalElement(browserRendererId, toLogicalElement(element, /* allow existing contents */ true), componentId, appendContent);\n}\n\nexport function getRendererer(browserRendererId: number): BrowserRenderer | undefined {\n  return browserRenderers[browserRendererId];\n}\n\nexport function renderBatch(browserRendererId: number, batch: RenderBatch): void {","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/294cab2f9b2e03af6b953820c7ab497c3c8b7ad9/src/Components/Web.JS/src/Rendering/Renderer.ts#L25-L61","documentation":"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.","triggerScenarios":"Server attaching a root component with a selector suffixed '::before' (e.g. via component descriptor or RegisterForJavaScript with a prepend target).","commonSituations":"Assuming symmetric '::after'/'::before' support; copy-paste of an '::after' selector pattern with '::before'; older docs/tutorials implying prepend is supported.","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."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Reject '::before' selectors before attach.\nfunction assertSelector(s: string) {\n  if (s.endsWith('::before')) throw new Error(\"'::before' is not supported; use a real container\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["blazor","root-components","selector","dom"],"analyzedSha":"294cab2f9b2e03af6b953820c7ab497c3c8b7ad9","analyzedAt":"2026-08-06T20:08:02.189Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}