Skip to content

Fix RangeError in PredictiveBackEvent when Android sends EDGE_NONE - #191306

Open
muhammadkamel wants to merge 2 commits into
flutter:masterfrom
muhammadkamel:fix/services-predictive-back-swipe-edge
Open

muhammadkamel wants to merge 2 commits into
flutter:masterfrom
muhammadkamel:fix/services-predictive-back-swipe-edge

Conversation

@muhammadkamel

@muhammadkamel muhammadkamel commented Aug 18, 2026 •

Copy link
Copy Markdown
Contributor

This is the framework/services-only split of #185140, per Piinks' decoupling guidance and the Material/Cupertino freeze in this repository (#188444).

On some Android 14+ devices, the platform sends swipeEdge: 2 (BackEvent.EDGE_NONE) for button-triggered predictive back events. PredictiveBackEvent.fromMap previously indexed SwipeEdge.values[2], which threw a RangeError because the enum only has left and right.

This PR:

  • Maps platform swipeEdge values explicitly (0 → left, 1 → right, 2 and unknown → left) so fromMap never throws
  • Leaves SwipeEdge unchanged (no new none value), because adding an enum case would require an exhaustive-switch update in frozen Material code
  • Continues to treat button events via isButtonEvent (touchOffset == null or Offset.zero with zero progress), which matches the crash payload from the issue

Material widget tests and transition behavior for EDGE_NONE belong in material_ui in flutter/packages. A dedicated SwipeEdge.none value can be added later if Material is no longer frozen here, or ported with that follow-up.

Fixes #186168

Pre-launch Checklist

  • I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
  • I read the [AI contribution guidelines] and understand my responsibilities, or I am not using AI tools.
  • I read the [Tree Hygiene] wiki page, which explains my responsibilities.
  • I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement].
  • I signed the [CLA].
  • I listed at least one issue that this PR fixes in the description above.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or this PR is [test-exempt].
  • I followed the [breaking change policy] and added [Data Driven Fixes] where supported.
  • All existing and new tests are passing.

Android can send swipeEdge=2 (BackEvent.EDGE_NONE) for button-triggered
predictive back events, which previously crashed fromMap. Map that value
to SwipeEdge.none instead of indexing SwipeEdge.values.

Fixes flutter#186168

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new SwipeEdge.none enum value to represent button-triggered back events (corresponding to Android's BackEvent.EDGE_NONE). It updates PredictiveBackEvent parsing, isButtonEvent detection, and page transitions to handle this new state, and adds comprehensive unit tests. Feedback suggests explicitly casting map['swipeEdge'] to int and asserting it is non-null during deserialization to maintain type safety and prevent silently ignoring malformed values.

Comment on lines +51 to +55
swipeEdge: switch (map['swipeEdge']) {
0 => SwipeEdge.left,
1 => SwipeEdge.right,
2 || _ => SwipeEdge.none,
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To maintain type safety and consistency with how other fields (like progress and touchOffset) are extracted from the map, we should explicitly cast map['swipeEdge'] to int and assert that it is non-null. This prevents silently ignoring null or malformed values, which would otherwise be incorrectly treated as SwipeEdge.none and could mask integration bugs.

Suggested change
swipeEdge: switch (map['swipeEdge']) {
0 => SwipeEdge.left,
1 => SwipeEdge.right,
2 || _ => SwipeEdge.none,
},
swipeEdge: switch (map['swipeEdge']! as int) {
0 => SwipeEdge.left,
1 => SwipeEdge.right,
_ => SwipeEdge.none,
},

@github-actions

Copy link
Copy Markdown

This pull request contains changes to Material or Cupertino, which are currently frozen in this repository.

Changes should be made in material_ui and/or cupertino_ui in the flutter/packages repository.

Please refer to #188444 for instructions.

@github-actions github-actions Bot added framework flutter/packages/flutter repository. See also f: labels. f: material design labels Aug 18, 2026
Material is frozen in flutter/flutter. Map Android EDGE_NONE to an
existing SwipeEdge value so fromMap no longer throws, without adding
a new enum case that would require a frozen exhaustive switch update.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Android] PredictiveBackEvent.fromMap does not guard against invalid swipeEdge value

1 participant