UIPageViewController crashes with _UIQueuingScrollView state inconsistency on iOS 26

UIPageViewController crashes with _UIQueuingScrollView state inconsistency on iOS 26

We are experiencing two types of crashes in UIPageViewController (transition style .scroll) that only occur on iOS 26. These crashes do not occur on iOS 18 or earlier with the same code.

Crash 1: "No view controller managing visible view"

NSInternalInconsistencyException:
No view controller managing visible view <_UIQueuingScrollView: 0x...>

-[UIPageViewController _flushViewController:animated:]
-[UIPageViewController _setViewControllers:withTransition:animated:completion:]

This occurs when calling setViewControllers(_:direction:animated:completion:) after a swipe gesture, particularly when didFinishAnimating delegate method does not fire.

Crash 2: "Duplicate states in queue"

NSInternalInconsistencyException:
Duplicate states in queue for view: <UIView: 0x...>

-[_UIQueuingScrollView _enqueueCompletionState:]
-[_UIQueuingScrollView _enqueueAnimatedScrollInDirection:withRevealView:coverView:stashedView:translation:]

This occurs when programmatic page changes (setViewControllers with animated: true) overlap with internal _UIQueuingScrollView state that has not been fully cleaned up.

Reproduction Steps

  1. Create a UIPageViewController with .scroll transition style
  2. Swipe partially (without completing the page transition), then release
  3. Immediately tap a button that calls setViewControllers(_:direction:animated:completion:)
  4. Repeat a few times — the crash occurs intermittently

Combining swipe gestures with programmatic setViewControllers calls reliably triggers one of the two crashes within a few attempts.

Root Cause Analysis

On iOS 26, the UIPageViewControllerDelegate method pageViewController(_:didFinishAnimating:previousViewControllers:transitionCompleted:) sometimes does not fire after a swipe gesture is cancelled or completed. This leaves _UIQueuingScrollView in a dirty internal state (pending transition data not cleared). A subsequent setViewControllers call then encounters this stale state and triggers an assertion failure.

The crash stack traces are entirely within UIKit internals (_UIQueuingScrollView, UIPageViewController), with no app code in the crashing frames.

Environment

  • Xcode 26.4.1
  • iOS 26 (all beta versions tested)
  • iPhone 17, iPhone 16 Pro, iPhone 16 Pro Max (simulator and device)
  • UIPageViewController with transitionStyle: .scroll
  • Does not reproduce on iOS 18 or earlier
UIPageViewController crashes with _UIQueuingScrollView state inconsistency on iOS 26
 
 
Q