dotnet/aspnetcore · error · Error

No enhanced programmatic navigation handler has been…

Error message

No enhanced programmatic navigation handler has been attached

What it means

Programmatic enhanced navigation (NavigationManager.NavigateTo with forceLoad=false under enhanced nav) is dispatched to a single registered handler attached by the enhanced-navigation subsystem. If performProgrammaticEnhancedNavigation is called and no handler has been attached via attachProgrammaticEnhancedNavigationHandler, the framework cannot route the request and throws — hasProgrammaticEnhancedNavigationHandler exists to let callers check first.

Solutions

  1. Check hasProgrammaticEnhancedNavigationHandler() before requesting a programmatic enhanced navigation.
  2. Ensure enhanced navigation is enabled and Blazor has started before issuing navigation calls.
  3. Use NavigateTo with forceLoad=true as a fallback when enhanced nav is unavailable.
  4. Verify Blazor.start completed and the enhanced-nav listener is attached.

Example fix

// before
NavigationManager.NavigateTo(url);
// after: guard for enhanced nav availability
if (hasProgrammaticEnhancedNavigationHandler()) {
  performProgrammaticEnhancedNavigation(url, false);
} else {
  // full page load fallback
  window.location.href = url;
}
Defensive patterns

Strategy: validation

Validate before calling

import { hasProgrammaticEnhancedNavigationHandler } from './NavigationUtils';
// before calling performProgrammaticEnhancedNavigation
if (!hasProgrammaticEnhancedNavigationHandler()) {
  // fallback to full page load
  window.location.href = absoluteInternalHref;
  return;
}

Try / catch

try {
  performProgrammaticEnhancedNavigation(href, replace);
} catch (e) {
  if (/No enhanced programmatic navigation handler/i.test((e as Error).message)) {
    window.location.href = href;
  } else throw e;
}

Prevention

When it happens

Trigger: Thrown at line 101 when performProgrammaticEnhancedNavigation(...) is called but programmaticEnhancedNavigationHandler is still undefined. Occurs if enhanced navigation is not active (no enhanced nav listener attached) but code requests a programmatic enhanced navigation.

Common situations: Calling NavigateTo from a component before enhanced navigation is initialized; disabling enhanced navigation via Blazor.start config while still calling enhanced nav interop; rendering a component in a non-enhanced-nav context (e.g. static SSR) that assumes enhanced nav exists.

Related errors


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

Appendix: source

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

export function attachEnhancedNavigationListener(listener: typeof enhancedNavigationListener) {
  enhancedNavigationListener = listener;
}

export function notifyEnhancedNavigationListeners(internalDestinationHref: string, interceptedLink: boolean) {
  enhancedNavigationListener?.(internalDestinationHref, interceptedLink);
}

export function hasProgrammaticEnhancedNavigationHandler(): boolean {
  return programmaticEnhancedNavigationHandler !== undefined;
}

export function attachProgrammaticEnhancedNavigationHandler(handler: typeof programmaticEnhancedNavigationHandler) {
  programmaticEnhancedNavigationHandler = handler;
}

export function performProgrammaticEnhancedNavigation(absoluteInternalHref: string, replace: boolean): void {
  if (!programmaticEnhancedNavigationHandler) {
    throw new Error('No enhanced programmatic navigation handler has been attached');
  }

  programmaticEnhancedNavigationHandler(absoluteInternalHref, replace);
}

function toBaseUriWithoutTrailingSlash(baseUri: string) {
  return baseUri.substring(0, baseUri.lastIndexOf('/'));
}

let testAnchor: HTMLAnchorElement;
export function toAbsoluteUri(relativeUri: string): string {
  testAnchor = testAnchor || document.createElement('a');
  testAnchor.href = relativeUri;
  return testAnchor.href;
}

function eventHasSpecialKey(event: MouseEvent) {
  return event.ctrlKey || event.shiftKey || event.altKey || event.metaKey;

View on GitHub (pinned to 3600ca084e)