You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
A NavigationChanged handler that redirects during Undo erases the redo history and leaves Undo() returning true forever without changing anything #95
Undo restores state through RestoreState (Navigation/Services/NavigationStack.cs:315), which raises NavigationChanged while UndoRedoService.Undo() (SimpleUndoRedoProvider.cs:66-89) is still running. If a handler navigates in response — the common "redirect" pattern — its NavigateTo registers a new undo action (NavigationStack.cs:84-107, 347-356) in the middle of the undo. Recording a new action clears the redo stack, and the provider ends up with an undo entry that just re-applies the redirect.
Repro (HEAD 9a11451), handler if (e.CurrentItem?.Id == "login") nav.NavigateTo(home);, then navigate to login (redirects to home), then to settings, then Undo repeatedly:
After the first undo, CanUndo never becomes false and every Undo() returns true while nothing visible changes, so an Undo button stays enabled and does nothing; the "Settings" redo entry is silently lost. Auth/route-guard redirects in NavigationChanged are a standard use of the event, so this isn't an exotic handler.
Suggested fix
Don't record navigations made while an undo or redo is being applied — the usual guard in undo frameworks:
set an "applying undo/redo" flag around RestoreState, and have the undo-registration path skip recording while it is set; or
raise NavigationChanged only after the provider has finished the undo/redo.
If the current behaviour is intended, document that handlers must not navigate during undo/redo.
Acceptance criteria
With the redirect handler above, repeated Undo() eventually returns false, and Redo() after the first undo restores "settings".
A test covers a handler that navigates during Undo and during Redo.
Related but distinct: #75 (a handler that throws during Undo), #90 (handler deadlock under the lock), #89 (concurrency with a shared provider).
Priority: Medium. Redirecting from NavigationChanged, the usual route-guard pattern, silently loses the redo history and leaves Undo permanently enabled while doing nothing. Navigation history is not corrupted beyond that, and nothing crashes.
Area / suggested assignee:NavigationStack.RestoreState and undo registration (NavigationStack.cs:84-107, 315, 347-356), and SimpleUndoRedoProvider.Undo/Redo. Owner: @matt-edmondson
Next step: add an "applying undo/redo" flag around RestoreState that suppresses registering new undo actions, or raise NavigationChanged after the provider finishes. Add tests for a redirecting handler during both Undo and Redo.
Activity
matt-edmondson commentedon Oct 29, 2026
Triage
NavigationChanged, the usual route-guard pattern, silently loses the redo history and leaves Undo permanently enabled while doing nothing. Navigation history is not corrupted beyond that, and nothing crashes.NavigationStack.RestoreStateand undo registration (NavigationStack.cs:84-107,315,347-356), andSimpleUndoRedoProvider.Undo/Redo. Owner: @matt-edmondsonRestoreStatethat suppresses registering new undo actions, or raiseNavigationChangedafter the provider finishes. Add tests for a redirecting handler during both Undo and Redo.Generated by Claude Code