{"record":{"id":"2a04c17080f08d77","repo":"dotnet/aspnetcore","slug":"unable-to-focus-an-invalid-element","errorCode":null,"errorMessage":"Unable to focus an invalid element.","messagePattern":"Unable to focus an invalid element\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/Components/Web.JS/src/DomWrapper.ts","lineNumber":21,"sourceCode":"\nimport '@microsoft/dotnet-js-interop';\n\nexport const domFunctions = {\n  focus,\n  focusBySelector,\n};\n\nfunction focus(element: HTMLOrSVGElement, preventScroll: boolean): void {\n  if (element instanceof HTMLElement) {\n    element.focus({ preventScroll });\n  } else if (element instanceof SVGElement) {\n    if (element.hasAttribute('tabindex')) {\n      element.focus({ preventScroll });\n    } else {\n      throw new Error('Unable to focus an SVG element that does not have a tabindex.');\n    }\n  } else {\n    throw new Error('Unable to focus an invalid element.');\n  }\n}\n\nfunction focusBySelector(selector: string) {\n  const element = document.querySelector(selector) as HTMLElement;\n  if (element) {\n    // If no explicit tabindex is defined, mark it as programmatically-focusable.\n    // This does actually add a new HTML attribute, but it shouldn't interfere with\n    // diffing because diffing only deals with the attributes you have in your code.\n    if (!element.hasAttribute('tabindex')) {\n      element.tabIndex = -1;\n    }\n\n    element.focus({ preventScroll: true });\n  }\n}\n","sourceCodeStart":3,"sourceCodeEnd":38,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/Components/Web.JS/src/DomWrapper.ts#L3-L38","documentation":"Blazor's interop `focus` helper moves keyboard focus to a DOM element passed from .NET (e.g. via `FocusAsync`/`@ref`). It branches on `instanceof HTMLElement` then `instanceof SVGElement`; if the value matches neither branch it is treated as invalid and the call throws. In practice the element is null/undefined, a non-element node, or a detached node whose identity no longer satisfies the instanceof checks.","triggerScenarios":"Calling `domFunctions.focus(element, preventScroll)` (directly or through `FocusAsync`) when `element` is null, undefined, a text node, a Document/Window, or an element reference held by .NET that was removed during a re-render so it is no longer an HTMLElement/SVGElement at runtime.","commonSituations":"Focusing an element inside an `@if` block that was toggled off before the await completed; holding a stale `ElementReference` across a hot reload or navigation; passing the result of `querySelector` that returned null; focusing a component host whose underlying DOM node was replaced by diffing.","solutions":["Null-check the element reference on the .NET side (`@if (myRef is not null) await myRef.FocusAsync();`) before invoking focus.","Ensure the focused element is a real, attached HTMLElement/SVGElement — verify `.isConnected` or that the owning `@if`/`@foreach` branch is still rendered at call time.","Prefer `focusBySelector` (CSS-selector overload) when you only have a selector: it silently no-ops when `querySelector` finds nothing instead of throwing.","For SVG targets, add `tabindex=\"-1\"` so the SVG branch succeeds rather than hitting the invalid/missing-tabindex errors."],"exampleFix":"// before\nconst el = document.querySelector('.maybe-gone');\nfocus(el, false); // el is null -> 'Unable to focus an invalid element.'\n\n// after\nconst el = document.querySelector('.maybe-gone');\nif (el instanceof HTMLElement || el instanceof SVGElement) {\n  focus(el, false);\n}","handlingStrategy":"type-guard","validationCode":"const el = document.querySelector(sel);\nif (!el) return; // nothing matched\nif (!(el instanceof HTMLElement) && !(el instanceof SVGElement)) {\n  throw new Error('Selector did not resolve a focusable element.');\n}\nfocus(el, false);","typeGuard":"function isFocusable(el: unknown): el is HTMLElement | SVGElement {\n  return el instanceof HTMLElement || el instanceof SVGElement;\n}","tryCatchPattern":"try { focus(element, preventScroll); }\ncatch (e) { if (/invalid element/.test(e.message)) { /* degrade silently or log */ } else throw e; }","preventionTips":["Null-check element references on the .NET side before FocusAsync.","Verify element.isConnected before focusing to avoid detached nodes.","Prefer focusBySelector when you only have a CSS selector — it no-ops on no match.","Add tabindex to SVG elements you intend to focus programmatically."],"tags":["dom","focus","interop","blazor","element-ref"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}