{"record":{"id":"556e063b60666408","repo":"dotnet/wpf","slug":"sr-uilesspagefunctionnotcallingonreturn","errorCode":null,"errorMessage":"SR.UiLessPageFunctionNotCallingOnReturn","messagePattern":"SR\\.UiLessPageFunctionNotCallingOnReturn","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Navigation/NavigationService.cs","lineNumber":3866,"sourceCode":"        // Two cases:\n        //     Parent is a PageFunction:  parentPF is not null.\n        //     Parent is a Non PageFunction: parentPF is null,\n        //                                   the valid info are parentIndex and ReturnEventArgs.\n        // The kind of navigation depends on finishingChildPageFunction.RemoveFromJournal:\n        //   - True: then do journal navigation to the parent page (and no journal entry created\n        //      for the finishing PF)\n        //   - False: do new navigation to the parent page.\n        private void NavigateToParentPage(PageFunctionBase finishingChildPageFunction, PageFunctionBase parentPF, object returnEventArgs, int parentIndex)\n        {\n            JournalEntry parentEntry = (JournalScope.Journal)[parentIndex];\n\n\n            if (parentPF != null)\n            {\n                // We shouldn't be navigating to a PageFunction that's UiLess at this stage.\n                // By now it should have started another navigation it was delegating to a child PF.\n                if (parentEntry.EntryType == JournalEntryType.UiLess)\n                    throw new InvalidOperationException(SR.UiLessPageFunctionNotCallingOnReturn);\n\n                NavigateInfo navInfo = finishingChildPageFunction.RemoveFromJournal ?\n                    new NavigateInfo(parentEntry.Source, NavigationMode.Back, parentEntry) :\n                    new NavigateInfo(parentEntry.Source, NavigationMode.New);\n                Navigate(parentPF, navInfo);\n                return;\n            }\n\n            // Handle the NonPF parent page case.\n            // Passing PageFunctionReturnInfo signals that the Return event should be raised for\n            // the finishing child PF.\n            PageFunctionReturnInfo pfRetInfo =\n                finishingChildPageFunction.RemoveFromJournal ?\n                new PageFunctionReturnInfo(finishingChildPageFunction, parentEntry.Source,\n                    NavigationMode.Back, parentEntry, returnEventArgs) :\n                new PageFunctionReturnInfo(finishingChildPageFunction, parentEntry.Source,\n                    NavigationMode.New, null, returnEventArgs);\n            if (parentEntry is JournalEntryUri)","sourceCodeStart":3848,"sourceCodeEnd":3884,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Navigation/NavigationService.cs#L3848-L3884","documentation":"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.","triggerScenarios":"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.","commonSituations":"Object-based PageFunctions (uiless) not calling OnReturn in their Start/flow logic; mixing uiless and visual PageFunctions incorrectly in nested flows.","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."],"exampleFix":"// before (uiless PF start)\nprotected override void Start() { var child = new ChildPF(); NavigationService.Navigate(child); /* never OnReturn */ }\n// after\nprotected override void Start() {\n    var child = new ChildPF();\n    child.Return += (s, e) => OnReturn(e);\n    NavigationService.Navigate(child);\n}","handlingStrategy":"validation","validationCode":"// ensure uiless PageFunctions always delegate:\nif (pf is PageFunctionBase p && !p.GetType().IsSubclassOf(typeof(PageFunction))) { /* verify Start() calls OnReturn */ }","typeGuard":null,"tryCatchPattern":"try { navService.Navigate(parentPF, navInfo); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"OnReturn\"))\n{ /* uiless parent did not delegate: fix Start() */ }","preventionTips":["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."],"tags":["wpf","navigation","pagefunction","journal"],"backgroundTag":"invalid-state-transition","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}