dotnet/wpf · error · InvalidOperationException
SR.Format(SR.InvalidOperation_MustImplementIPCCSOrHandleNavi…
Error message
SR.Format(SR.InvalidOperation_MustImplementIPCCSOrHandleNavigating, _bp != null ? _bp.GetType().ToString() : "null")
What it means
After AddBackEntry() journals the request, the resulting entry must carry a CustomContentState — either because the content implements IProvideCustomContentState or because a Navigating event handler supplied state. If je.CustomContentState is null, the service rolls back (RemoveBackEntry) and throws InvalidOperationException MustImplementIPCCSOrHandleNavigating naming the content type (or "null").
Solutions
- Implement IProvideCustomContentState on the navigated content class and return a CustomContentState from GetContentState()
- Handle the Navigating event and set e.ContentStateToSave to a CustomContentState instance
- Pass an explicit non-null CustomContentState to AddBackEntry(state)
Example fix
// before
navService.AddBackEntry(null); // page does not provide state
// after
public class MyPage : Page, IProvideCustomContentState
{
public CustomContentState GetContentState() => new MyPageState(this);
}
navService.AddBackEntry(null); // now valid via IProvideCustomContentState Defensive patterns
Strategy: validation
Validate before calling
bool providesState = navService.Content is IProvideCustomContentState || navigatingHandlerInstalled; if (!providesState) navService.AddBackEntry(new MyState()); // explicit state
Type guard
bool ContentProvidesState(NavigationService ns) => ns.Content is IProvideCustomContentState;
Try / catch
try { ns.AddBackEntry(state); }
catch (InvalidOperationException ex) when (ex.Message.Contains("CustomContentState")) {
// content type must implement IProvideCustomContentState
} Prevention
- Implement IProvideCustomContentState on navigable page classes
- Or set NavigatingEventArgs.ContentStateToSave in a Navigating handler
- Never rely on AddBackEntry(null) without either mechanism in place
When it happens
Trigger: Calling AddBackEntry(null) (or relying on it) when the current content object does not implement IProvideCustomContentState and no Navigating handler sets e.ContentStateToSave, so the journal entry ends with CustomContentState == null.
Common situations: Copy/pasting AddBackEntry sample code without implementing IProvideCustomContentState on the page class; renaming refactoring that dropped the interface; expecting AddBackEntry(null) to snapshot the page automatically (it does not).
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- SR.Format(SR.CustomContentStateMustBeSerializable, type)
- SR.InvalidOperation_AddBackEntryNoContent
- SR.InvalidOperation_CannotClearFwdStack
- SR.InvalidOperation_CantChangeJournalOwnership
- SR.InvalidOperation_NoJournal
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/dd60cc0b774a94ae.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Navigation/NavigationService.cs:1427
}
if (_bp == null)
throw new InvalidOperationException(SR.InvalidOperation_AddBackEntryNoContent);
_customContentStateToSave = state;
JournalEntry je = UpdateJournal(NavigationMode.New, JournalReason.AddBackEntry, null);
// Controls state is not saved by design (saveContent=false). If client applications
// require it to be synchronized with the CustomContentState, they can explicitly
// include it.
_customContentStateToSave = null;
// Since state=null is allowed on input, make sure we get an object either via the
// IProvideCustomContentState interface or from a Navigating event handler.
// Otherwise it doesn't make sense to add a journal entry.
if (je != null && je.CustomContentState == null)
{
RemoveBackEntry();
throw new InvalidOperationException(
SR.Format(SR.InvalidOperation_MustImplementIPCCSOrHandleNavigating,
_bp != null ? _bp.GetType().ToString() : "null"));
}
}
/// <summary>
/// Remove the first JournalEntry from NavigationWindow's back history
/// </summary>
public JournalEntry RemoveBackEntry()
{
if (IsDisposed)
{
return null;
}
if (JournalScope == null)
return null; //(Normally, no exception is thrown if there is no back entry.)
return JournalScope.RemoveBackEntry();
}View on GitHub (pinned to 81131a70a4)