dotnet/wpf · error · InvalidOperationException
SR.UiLessPageFunctionNotCallingOnReturn
Error message
SR.UiLessPageFunctionNotCallingOnReturn
What it means
When a PageFunction finishes, the parent journal entry must be a normal (non-uiless) entry. If the parent entry is marked UiLess, the parent PageFunction should already have delegated navigation to a child via OnReturn; reaching navigation with a uiless parent means it did not, so the service throws.
Solutions
- Ensure uiless PageFunction.Start() always ends with a call to OnReturn (or navigation to another child).
- Verify nested PageFunction chains delegate correctly through OnReturn.
- Review JournalEntryType handling; make parent entries non-uiless by giving the parent an actual UI or correct delegation.
- Step through HandleFinish with the journal to confirm entry types.
Example fix
// before (uiless PF start)
protected override void Start() { var child = new ChildPF(); NavigationService.Navigate(child); /* never OnReturn */ }
// after
protected override void Start() {
var child = new ChildPF();
child.Return += (s, e) => OnReturn(e);
NavigationService.Navigate(child);
} Defensive patterns
Strategy: validation
Validate before calling
// ensure uiless PageFunctions always delegate:
if (pf is PageFunctionBase p && !p.GetType().IsSubclassOf(typeof(PageFunction))) { /* verify Start() calls OnReturn */ } Try / catch
try { navService.Navigate(parentPF, navInfo); }
catch (InvalidOperationException ex) when (ex.Message.Contains("OnReturn"))
{ /* uiless parent did not delegate: fix Start() */ } Prevention
- Every uiless PageFunction.Start() must end by calling OnReturn.
- Wire child.Return to parent OnReturn in nested flows.
- Keep uiless PageFunctions derived via Object-based pattern correctly.
- Trace journal entry types during nested PF development.
When it happens
Trigger: A uiless (no UI) PageFunction completes a child, but navigation proceeds to the parent while its journal entry type is UiLess — i.e. the uiless parent failed to call OnReturn and delegate to another PageFunction as required.
Common situations: Object-based PageFunctions (uiless) not calling OnReturn in their Start/flow logic; mixing uiless and visual PageFunctions incorrectly in nested flows.
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_CannotReenterPageFunction
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/556e063b60666408.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Navigation/NavigationService.cs:3866
// Two cases:
// Parent is a PageFunction: parentPF is not null.
// Parent is a Non PageFunction: parentPF is null,
// the valid info are parentIndex and ReturnEventArgs.
// The kind of navigation depends on finishingChildPageFunction.RemoveFromJournal:
// - True: then do journal navigation to the parent page (and no journal entry created
// for the finishing PF)
// - False: do new navigation to the parent page.
private void NavigateToParentPage(PageFunctionBase finishingChildPageFunction, PageFunctionBase parentPF, object returnEventArgs, int parentIndex)
{
JournalEntry parentEntry = (JournalScope.Journal)[parentIndex];
if (parentPF != null)
{
// We shouldn't be navigating to a PageFunction that's UiLess at this stage.
// By now it should have started another navigation it was delegating to a child PF.
if (parentEntry.EntryType == JournalEntryType.UiLess)
throw new InvalidOperationException(SR.UiLessPageFunctionNotCallingOnReturn);
NavigateInfo navInfo = finishingChildPageFunction.RemoveFromJournal ?
new NavigateInfo(parentEntry.Source, NavigationMode.Back, parentEntry) :
new NavigateInfo(parentEntry.Source, NavigationMode.New);
Navigate(parentPF, navInfo);
return;
}
// Handle the NonPF parent page case.
// Passing PageFunctionReturnInfo signals that the Return event should be raised for
// the finishing child PF.
PageFunctionReturnInfo pfRetInfo =
finishingChildPageFunction.RemoveFromJournal ?
new PageFunctionReturnInfo(finishingChildPageFunction, parentEntry.Source,
NavigationMode.Back, parentEntry, returnEventArgs) :
new PageFunctionReturnInfo(finishingChildPageFunction, parentEntry.Source,
NavigationMode.New, null, returnEventArgs);
if (parentEntry is JournalEntryUri)View on GitHub (pinned to 81131a70a4)