dotnet/wpf · error · InvalidOperationException
SR.InvalidOperation_CantChangeJournalOwnership
Error message
SR.InvalidOperation_CantChangeJournalOwnership
What it means
NavigationService.InvalidateJournalNavigationScope() detaches the service from its journal, but refuses while a Back/Forward (uncommitted) journal navigation is pending, throwing InvalidOperationException CantChangeJournalOwnership. Changing journal ownership mid-navigation would lose the pending navigation target.
Solutions
- Defer RemoveChild/reparenting until navigation completes (LoadCompleted/NavigationFailed)
- Do not call GoBack/GoForward immediately before removing a frame; commit pending navigations first
- Restructure so journal ownership changes happen outside navigation event handlers
Example fix
// before navService.GoBack(); parent.RemoveChild(frame); // pending back navigation -> throws // after navService.GoBack(); navService.LoadCompleted += (s, e) => parent.RemoveChild(frame);
Defensive patterns
Strategy: validation
Validate before calling
bool pending = frame.NavigationService.GetType()
.GetProperty("Journal", BindingFlags.NonPublic|BindingFlags.Instance) != null; // in practice: defer removal
if (isNavigating) DeferRemoval(frame); else parent.RemoveChild(frame); Try / catch
try { parent.RemoveChild(frame); }
catch (InvalidOperationException ex) when (ex.Message.Contains("journal")) {
frame.NavigationService.LoadCompleted += (s, e) => parent.RemoveChild(frame);
} Prevention
- Remove/reparent frames only between navigations (after LoadCompleted)
- Never mutate the frame tree from Navigating handlers triggered by Back/Forward
- Design teardown code to await idle navigation state
When it happens
Trigger: Calling RemoveChild (e.g. detaching a child frame/navigation service from a parent) while _journalScope.Journal.HasUncommittedNavigation is true — a Back or Forward navigation was started but not yet committed.
Common situations: Removing/reparenting a Frame from the visual tree in response to navigation events; tearing down navigation hosts in Navigating/FragmentNavigation handlers; dynamic layout that swaps frames during user back/forward clicks.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- SR.Format(SR.CustomContentStateMustBeSerializable, type)
- SR.Format(SR.InvalidOperation_MustImplementIPCCSOrHandleNavi…
- SR.InvalidOperation_AddBackEntryNoContent
- SR.InvalidOperation_CannotClearFwdStack
- SR.InvalidOperation_NoJournal
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/dfdc3efb80d75571.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Navigation/NavigationService.cs:562
/// <returns></returns>
private static INavigatorBase FindTargetInNavigationWindow(NavigationWindow navigationWindow, string navigatorId)
{
if (navigationWindow != null)
{
return navigationWindow.NavigationService.FindTarget(navigatorId);
}
return null;
}
internal void InvalidateJournalNavigationScope()
{
// If there is a pending journal navigation (Back/Fwd), the JournalNavigationScope cannot
// be changed. (If it is a _new_ navigation, we're OK; it will be recorded in the new
// applicable journal.)
// _navStatus or _navigateQueueItem are not checked here, because they are set only after
// raising the Navigating event, while an event handler might cause journal ownership to change.
if (_journalScope != null && _journalScope.Journal.HasUncommittedNavigation)
throw new InvalidOperationException(SR.InvalidOperation_CantChangeJournalOwnership);
_journalScope = null;
for (int i = ChildNavigationServices.Count - 1; i >= 0; i--)
{
((NavigationService)ChildNavigationServices[i]).InvalidateJournalNavigationScope();
}
}
internal void OnParentNavigationServiceChanged()
{
NavigationService oldParent = _parentNavigationService;
NavigationService newParent = ((DependencyObject)INavigatorHost).GetValue(NavigationServiceProperty) as NavigationService;
if (newParent == oldParent)
return;
// Remove from old parent's listView on GitHub (pinned to 81131a70a4)