dotnet/aspnetcore · error · NotSupportedException
To support navigation locks
Error message
To support navigation locks, {GetType().Name} must override {nameof(SetNavigationLockState)} What it means
Thrown by the default virtual SetNavigationLockState when the first location-changing handler is registered. NavigationLock support requires the host to physically suppress URI changes until NotifyLocationChangingAsync confirms them; the base class cannot do that, so it demands an override. Without the override, registering a NavigationLock would silently no-op and break the contract.
Solutions
- Override SetNavigationLockState(bool) in your NavigationManager subclass to actually enable/disable interception in your host.
- Use the built-in Server/WebAssembly NavigationManager implementations, which already override it.
- Do not call RegisterLocationChangingHandler (or render a NavigationLock component) against a manager that does not support locks.
- In tests, use the framework test double (e.g. FakeNavigationManager or a derived RemoteNavigationManager) that supplies the overrides.
Example fix
// before: subclass missing the override, registering a lock throws
public class CustomNavManager : NavigationManager { }
// _ = manager.RegisterLocationChangingHandler(...); // throws
// after: override so the host honors the lock flag
public class CustomNavManager : NavigationManager
{
private bool _locked;
protected override void SetNavigationLockState(bool value) => _locked = value;
} Defensive patterns
Strategy: validation
Validate before calling
var t = navManager.GetType();
var overriden = t.GetMethod(nameof(NavigationManager.SetNavigationLockState), BindingFlags.Instance | BindingFlags.NonPublic)!.DeclaringType != typeof(NavigationManager);
if (!overriden) throw new NotSupportedException($"{t.Name} cannot host navigation locks: override SetNavigationLockState."); Try / catch
try { manager.RegisterLocationChangingHandler(handler); }
catch (NotSupportedException ex) when (ex.Message.Contains("SetNavigationLockState"))
{ /* use a capable manager or skip the lock */ } Prevention
- Use the framework managers in production.
- In a custom host, override SetNavigationLockState and physically block URI changes while locked.
- Do not render NavigationLock components against managers that lack lock support.
When it happens
Trigger: RegisterLocationChangingHandler is called and the handler list transitions from empty to one entry, which calls SetNavigationLockState(true). If the concrete NavigationManager type does not override SetNavigationLockState, this NotSupportedException fires immediately on first registration.
Common situations: A test or custom host subclasses NavigationManager directly and exercises NavigationLock or RegisterLocationChangingHandler; a third-party Blazor host (e.g. a non-Microsoft MAUI/gtk host) that has not implemented navigation locking.
Related errors
- To support navigation locks
- An exception occurred while dispatching a location changed…
- ' ' has not been initialized.
- No component found for route
- Setting and properties simultaneously is not supported. Use…
AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11).
Data as JSON: /api/errors/02a4ab93dca559b3.
Report an issue: GitHub.
Appendix: source
Thrown at src/Components/Components/src/NavigationManager.cs:569
}
}
/// <summary>
/// Handles exceptions thrown in location changing handlers.
/// </summary>
/// <param name="ex">The exception to handle.</param>
/// <param name="context">The context passed to the handler.</param>
protected virtual void HandleLocationChangingHandlerException(Exception ex, LocationChangingContext context)
=> throw new InvalidOperationException($"To support navigation locks, {GetType().Name} must override {nameof(HandleLocationChangingHandlerException)}");
/// <summary>
/// Sets whether navigation is currently locked. If it is, then implementations should not update <see cref="Uri"/> and call
/// <see cref="NotifyLocationChanged(bool)"/> until they have first confirmed the navigation by calling
/// <see cref="NotifyLocationChangingAsync(string, string?, bool)"/>.
/// </summary>
/// <param name="value">Whether navigation is currently locked.</param>
protected virtual void SetNavigationLockState(bool value)
=> throw new NotSupportedException($"To support navigation locks, {GetType().Name} must override {nameof(SetNavigationLockState)}");
/// <summary>
/// Registers a handler to process incoming navigation events.
/// </summary>
/// <param name="locationChangingHandler">The handler to process incoming navigation events.</param>
/// <returns>An <see cref="IDisposable"/> that can be disposed to unregister the location changing handler.</returns>
public IDisposable RegisterLocationChangingHandler(Func<LocationChangingContext, ValueTask> locationChangingHandler)
{
AssertInitialized();
var isFirstHandler = _locationChangingHandlers.Count == 0;
_locationChangingHandlers.Add(locationChangingHandler);
if (isFirstHandler)
{
SetNavigationLockState(true);
}View on GitHub (pinned to 3600ca084e)