dotnet/aspnetcore · error

The event ' ' is already registered.

Error message

The event '${eventName}' is already registered.

What it means

Thrown by registerCustomEventType when an event name has already been added to the eventTypeRegistry. Blazor disallows duplicate registrations because each custom event name maps to exactly one eventargs-builder; a second mapping would make it ambiguous which data to supply to the handler. The guard runs before any aliasing logic so it catches both genuine duplicates and accidental re-registration.

Solutions

  1. Search the codebase for duplicate registerCustomEventType calls with the same event name and remove or consolidate them.
  2. Guard the registration with a check: only register if the event is not already known (call from a module loaded once).
  3. If two libraries legitimately need the event, pick a unique prefix per library (e.g. 'libA:myevent').
  4. Ensure the registering script is loaded exactly once via script tags or a singleton import.

Example fix

// before
Blazor.registerCustomEventType('myevent', { createEventArgs: e => ({ value: e.detail }) });
// loaded again elsewhere -> throws

// after: idempotent guard
if (!Blazor._customEventRegistered?.('myevent')) {
  Blazor.registerCustomEventType('myevent', { createEventArgs: e => ({ value: e.detail }) });
}
Defensive patterns

Strategy: validation

Validate before calling

// Before registering, check if already registered.
// Blazor exposes eventNameAliasRegisteredCallbacks; for a custom guard keep a Set.
const registered = (globalThis.__blazorCustomEvents ??= new Set());
if (!registered.has(eventName)) {
  Blazor.registerCustomEventType(eventName, options);
  registered.add(eventName);
}

Type guard

// No public API to query the registry; track locally.
function isCustomEventRegistered(name: string): boolean {
  return (globalThis.__blazorCustomEvents ?? new Set()).has(name);
}

Try / catch

try {
  Blazor.registerCustomEventType(name, options);
} catch (e) {
  if (e instanceof Error && /already registered/.test(e.message)) {
    // benign duplicate (e.g. HMR) — ignore
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling Blazor.registerCustomEventType('myevent', {...}) twice with the same first argument in the same JS context; loading two JS files that both register the same event; importing a library that registers a custom event after the app already registered it.

Common situations: A shared component library and app code both register 'copy' or 'paste'; a hot-reload / HMR cycle that re-executes the registration module without a guard; bundling two versions of a Blazor extensions package.

Related errors


AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11). Data as JSON: /api/errors/5a427c98796e7f17. Report an issue: GitHub.

Appendix: source

Thrown at src/Components/Web.JS/src/Rendering/Events/EventTypes.ts:23

  browserEventName?: string;
  createEventArgs?: (event: Event) => unknown;
}

const eventTypeRegistry: Map<string, EventTypeOptions> = new Map();
const browserEventNamesToAliases: Map<string, string[]> = new Map();
const createBlankEventArgsOptions: EventTypeOptions = { createEventArgs: () => ({}) };

export const eventNameAliasRegisteredCallbacks: ((aliasEventName: string, browserEventName) => void)[] = [];

export function registerCustomEventType(eventName: string, options: EventTypeOptions): void {
  if (!options) {
    throw new Error('The options parameter is required.');
  }

  // There can't be more than one registration for the same event name because then we wouldn't
  // know which eventargs data to supply.
  if (eventTypeRegistry.has(eventName)) {
    throw new Error(`The event '${eventName}' is already registered.`);
  }

  // When aliasing a browser event, the custom event name must be different from the browser event name
  // to avoid double-triggering (once for the browser event, once for the custom event wrapper)
  if (options.browserEventName && eventName === options.browserEventName) {
    throw new Error(`The custom event '${eventName}' cannot have the same name as its browserEventName '${options.browserEventName}'. Choose a different name for the custom event.`);
  }

  // If applicable, register this as an alias of the given browserEventName
  if (options.browserEventName) {
    const aliasGroup = browserEventNamesToAliases.get(options.browserEventName);
    if (aliasGroup) {
      aliasGroup.push(eventName);
    } else {
      browserEventNamesToAliases.set(options.browserEventName, [eventName]);
    }

    // For developer convenience, it's allowed to register the custom event type *after*

View on GitHub (pinned to 3600ca084e)