diff --git a/web/src/elements/dialogs/directives.ts b/web/src/elements/dialogs/directives.ts index 9d6caf97f0..ab97d9700b 100644 --- a/web/src/elements/dialogs/directives.ts +++ b/web/src/elements/dialogs/directives.ts @@ -3,6 +3,7 @@ import { checkObjectShallowEquality } from "#common/collections"; import { AKElement } from "#elements/Base"; import { asInvoker, type ModalTemplate } from "#elements/dialogs/invokers"; import type { DialogInit, TransclusionElementConstructor } from "#elements/dialogs/shared"; +import { ElementConstructorBoundary } from "#elements/errors/boundaries"; import type { LitPropertyRecord } from "#elements/types"; import { isAKElementConstructor, StrictUnsafe } from "#elements/utils/unsafe"; @@ -159,10 +160,22 @@ export function lookupElementConstructor( tagName: string, registry: CustomElementRegistry = window.customElements, ): T { + if (!tagName) { + // eslint-disable-next-line no-console + console.trace( + "No tag name provided for lookup. Did this value come from a different version of authentik?", + ); + + return ElementConstructorBoundary as unknown as T; + } + const ElementConstructor = registry.get(tagName); if (!ElementConstructor) { - throw new TypeError(`No custom element defined for tag name: ${tagName}`); + // eslint-disable-next-line no-console + console.trace(`No custom element defined for tag name: ${tagName}`); + + return ElementConstructorBoundary as unknown as T; } return ElementConstructor as unknown as T; diff --git a/web/src/elements/errors/boundaries.ts b/web/src/elements/errors/boundaries.ts new file mode 100644 index 0000000000..6ce9cfffa7 --- /dev/null +++ b/web/src/elements/errors/boundaries.ts @@ -0,0 +1,31 @@ +import { AKElement } from "#elements/Base"; +import { SlottedTemplateResult } from "#elements/types"; + +import { msg } from "@lit/localize"; +import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; +import { html } from "lit-html"; + +import PFAlert from "@patternfly/patternfly/components/Alert/alert.css"; + +/** + * A fallback element to render when a custom element fails to load, either due to a missing import, + * or a version mismatch between the element's definition and its usage. + */ +@customElement("ak-element-missing") +export class ElementConstructorBoundary extends AKElement { + public styles = [PFAlert]; + + protected override render(): SlottedTemplateResult { + return html``; + } +}