dotnet/aspnetcore · error · Error

Only one interactive runtime may enable navigation…

Error message

Only one interactive runtime may enable navigation interception at a time.

What it means

Blazor allows only one interactive runtime to own router-level navigation interception at a time. setHasInteractiveRouter stores the rendererId of that owner and refuses to overwrite it with a different rendererId. hasInteractiveRouter/getInteractiveRouterRendererId expose the current owner. This enforces a single source of truth for link-click interception when multiple renderers coexist.

Solutions

  1. Ensure only one interactive runtime registers as the interactive router on a page (typical: one render mode globally or per-page).
  2. Avoid loading both blazor.web.js and a second interactive host on the same page.
  3. Confirm you are not double-invoking Blazor.start or re-initializing the runtime.
  4. Align client and server Blazor versions so the renderer registration happens once.

Example fix

// before: two renderers both call setHasInteractiveRouter
// after: only one interactive render mode per page
// App.razor — pick ONE:
<Routes @rendermode="InteractiveServer" />
<!-- or -->
<Routes @rendermode="InteractiveWebAssembly" />
<!-- not both registered as routers simultaneously
Defensive patterns

Strategy: validation

Validate before calling

import { hasInteractiveRouter } from './NavigationUtils';
// before calling setHasInteractiveRouter
if (hasInteractiveRouter()) {
  // another renderer already owns routing; do not register again
  return;
}

Try / catch

try {
  setHasInteractiveRouter(rendererId);
} catch (e) {
  if (/Only one interactive runtime/i.test((e as Error).message)) {
    // pick one render mode; reload to reset
    window.location.reload();
  } else throw e;
}

Prevention

When it happens

Trigger: Thrown at line 154 when setHasInteractiveRouter(rendererId) is called with a rendererId different from the already-set interactiveRouterRendererId (which is not undefined). Happens when a second interactive runtime attempts to register as the router after a first one already did.

Common situations: Loading both a Server and a WebAssembly interactive renderer with their own routers on the same page; misconfigured Auto render mode spinning up two interactive runtimes that both try to own the router; double-Blazor.start; version skew causing duplicate renderer initialization.

Related errors


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

Appendix: source

Thrown at src/Components/Web.JS/src/Services/NavigationUtils.ts:154

      if (candidate instanceof HTMLAnchorElement || candidate instanceof SVGAElement) {
        return candidate;
      }
    }
  }
  return null;
}

export function hasInteractiveRouter(): boolean {
  return interactiveRouterRendererId !== undefined;
}

export function getInteractiveRouterRendererId() : WebRendererId | undefined {
  return interactiveRouterRendererId;
}

export function setHasInteractiveRouter(rendererId: WebRendererId) {
  if (interactiveRouterRendererId !== undefined && interactiveRouterRendererId !== rendererId) {
    throw new Error('Only one interactive runtime may enable navigation interception at a time.');
  }

  interactiveRouterRendererId = rendererId;
}

View on GitHub (pinned to 3600ca084e)