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
- Check hasProgrammaticEnhancedNavigationHandler() before requesting a programmatic enhanced navigation.
- Ensure enhanced navigation is enabled and Blazor has started before issuing navigation calls.
- Use NavigateTo with forceLoad=true as a fallback when enhanced nav is unavailable.
- 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
- Always check hasProgrammaticEnhancedNavigationHandler before programmatic enhanced nav.
- Provide a full-page-load fallback path.
- Ensure Blazor.start completed and enhanced nav initialized.
- Treat enhanced nav as best-effort, not guaranteed.
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
- ' ' already initialized.
- Cannot perform enhanced form submission that changes the…
- Descriptors must be assigned a renderer ID before getting…
- Enhanced navigation does not support making a non-GET…
- Enhanced navigation does not support making a non-GET…
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)