Skip to content

iOS 26: every press fails with point.x != INFINITY since 0.21.9 when the app's frames read null (glass views) #3514

Closed as not planned

Description

@Marius-courquin

What happens

Since 0.21.9, on an iOS 26 simulator, every coordinate press in some apps fails with

NSInternalInconsistencyException: Invalid parameter not satisfying: point.x != INFINITY && point.y != INFINITY

snapshot, wait, screenshot and record keep working; only presses fail, by label or by raw press <x> <y>, and the failure survives a runner restart, a simulator reboot and an app reinstall. The runner logs, before every failing press:

AGENT_DEVICE_RUNNER_SYNTHESIZED_GESTURE_POLICY kind=coordinateTap context=unavailable fallbackAttempted=true

Reported downstream in https://github.com/Marius-courquin/vysu/issues/11 (Expo SDK 55, RN 0.83, react-native-screens 4.23 native Tabs, expo-glass-effect GlassView; iOS 26.3.1 simulator, Xcode 26.2, agent-device 0.21.9). The reporter narrowed it to an iOS 26 glass view in the hierarchy: the native UITabBarController bar, or a GlassView (isInteractive) in a header button with a JS tab bar. Presses in Settings work in the same session.

Why (read in the 0.21.26 package)

  • 0.21.6 to 0.21.8 build the synthesized-tap context from the screenshot size (frameSource=screenshot), which is always finite.
  • From 0.21.9 (fix(ios): target the active window for foldable interactions #2724, active window for foldables), synthesizedCoordinateContext (RunnerTests+SynthesizedInteraction.swift:385) takes its frame from resolveRunnerWindow(app:) (RunnerTests+Interaction.swift:236): the first window whose frame is not isEmpty, else (nil, app.frame).
  • In the glass case the app's and its windows' frames must read as CGRect.null (inferred: it is the only value that gives both context=unavailable and an infinite anchor below; I could not observe it on the reporter's app): no window qualifies, guard let window returns nil, hence context=unavailable.
  • The XCTest fallback, interactionCoordinate(app:x:y:) (RunnerTests+Interaction.swift:583), anchors on app.coordinate(withNormalizedOffset: (0, 0)); with app.frame == .null its origin is (inf, inf), and tap() raises the assertion.
  • Note also that !frame.isEmpty lets a CGRect.infinite window through (it is not empty), which the finiteness guard then rejects the same way.

Checked

On an app with the same kind of native tab bar (expo-router NativeTabs, react-native-screens 4.25.2, Expo SDK 56, RN 0.85.3, iOS 26.2 simulator) whose Application and Window frames read finite ({0,0,402,874}), 0.21.6 presses a native tab and an in-screen control by label and by coordinates (frameSource=screenshot … fallbackAttempted=false). The reporter's app, whose frames read null, fails on every version from 0.21.9; the code path is unchanged in 0.21.26.

Suggested fix

  1. resolveRunnerWindow: accept only windows whose frame is finite and non-empty.
  2. When none qualifies, build the context from the screenshot size and the main display, as 0.21.8 did, instead of returning nil.
  3. interactionCoordinate on iOS: when app.frame is null or not finite, anchor on the screen instead (e.g. the springboard application's coordinate space), so the fallback cannot raise.
  4. Failing that, return a typed error ("the app's accessibility frame is unavailable") rather than letting the XCTest assertion through.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions