dotnet/maui · error · InvalidOperationException
Handler is already being set elsewhere
Error message
Handler is already being set elsewhere
What it means
Thrown by Element.SetHandler when _previousHandler is non-null at entry. SetHandler uses _previousHandler as a reentrancy sentinel: it is set at the start and cleared in a finally block. If it is still set on re-entry, another handler change is already in flight on the same element — meaning OnHandlerChangingCore or OnHandlerChangedCore triggered a recursive SetHandler call before the first completed.
Source
Thrown at src/Controls/src/Core/Element/Element.cs:1082
private protected virtual void OnHandlerChangingCore(HandlerChangingEventArgs args)
{
HandlerChanging?.Invoke(this, args);
OnHandlerChanging(args);
}
IElementHandler _previousHandler;
void SetHandler(IElementHandler newHandler)
{
if (newHandler == _handler)
return;
try
{
// If a handler is getting changed before the end of this method
// Something is wired up incorrectly
if (_previousHandler != null)
throw new InvalidOperationException("Handler is already being set elsewhere");
_previousHandler = _handler;
OnHandlerChangingCore(new HandlerChangingEventArgs(_previousHandler, newHandler));
_handler = newHandler;
// Only call disconnect if the previous handler is still connected to this virtual view.
// If a handler is being reused for a different VirtualView then the virtual
// view would have already rolled
if (_previousHandler?.VirtualView == this)
_previousHandler?.DisconnectHandler();
if (_handler?.VirtualView != this)
_handler?.SetVirtualView(this);
OnHandlerChangedCore();
}View on GitHub (pinned to f377ff1c5e)
Solutions
- Do not set element.Handler from within OnHandlerChanging/OnHandlerChanged overrides or their event handlers.
- If you need to swap handlers, defer it (Dispatcher.Dispatch or a flag) so it runs after the current SetHandler completes.
- Audit custom handler DisconnectHandler/SetVirtualView implementations for code that re-enters SetHandler.
- Remove HandlerChanged/HandlerChanging subscriptions that mutate the Handler.
Example fix
// before
protected override void OnHandlerChanged()
{
base.OnHandlerChanged();
this.Handler = CreateNewHandler(); // re-enters SetHandler -> throws
}
// after — defer
protected override void OnHandlerChanged()
{
base.OnHandlerChanged();
Dispatcher.Dispatch(() => this.Handler = CreateNewHandler());
} Defensive patterns
Strategy: validation
Validate before calling
// Do not reassign Handler from within OnHandlerChanging/OnHandlerChanged.
// Use a deferred action if a reassignment is necessary.
bool _reassignPending;
protected override void OnHandlerChanged()
{
base.OnHandlerChanged();
_reassignPending = true;
Dispatcher.Dispatch(() => { if (_reassignPending) { _reassignPending = false; /* swap */ } });
} Try / catch
try { element.Handler = newHandler; }
catch (InvalidOperationException ex) when (ex.Message == "Handler is already being set elsewhere")
{
// defer the reassignment to avoid reentrancy
element.Dispatcher.Dispatch(() => element.Handler = newHandler);
} Prevention
- Never set element.Handler from OnHandlerChanging/OnHandlerChanged overrides or their events.
- Audit custom handler DisconnectHandler/SetVirtualView for re-entrant SetHandler calls.
- Defer handler swaps with Dispatcher.Dispatch when triggered inside lifecycle callbacks.
When it happens
Trigger: During OnHandlerChanging/OnHandlerChanged overrides or event handlers, code sets the Handler again (e.g., setting element.Handler = ... inside a HandlerChanged handler), causing re-entry into SetHandler while _previousHandler is non-null. Also triggered by a handler whose DisconnectHandler or SetVirtualView re-assigns the handler.
Common situations: Custom element overriding OnHandlerChanging and reassigning Handler in the same callback; a handler implementation whose DisconnectHandler triggers a re-connect; event handlers wired to HandlerChanged that mutate the Handler; faulty DI/handler-factory that re-assigns during setup.
Related errors
- You MUST invoke LoadApplication () before calling base.Finis
- NavigationPage must have a root Page before being used. Eith
- call Forms.Init() before this
- application
- Please provide a main window in your app
AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13).
Data as JSON: /api/errors/feb1b73bd458855c.
Report an issue: GitHub.