Skip to content

Fix/predictive back event swipe edge out of bounds - #185140

Open
muhammadkamel wants to merge 18 commits into
flutter:masterfrom
muhammadkamel:fix/predictive-back-event-swipe-edge-out-of-bounds
Open

muhammadkamel wants to merge 18 commits into
flutter:masterfrom
muhammadkamel:fix/predictive-back-event-swipe-edge-out-of-bounds

Conversation

@muhammadkamel

@muhammadkamel muhammadkamel commented Apr 16, 2026 •

Copy link
Copy Markdown
Contributor

This PR addresses a RangeError in PredictiveBackEvent.fromMap that occurs on Android devices when the predictive back gesture provides an unexpected swipeEdge index.

Description

On some Android 14+ devices/ROMs, the platform can send a swipeEdge value of 2 (BackEvent.EDGE_NONE) for button-triggered predictive back events. Since SwipeEdge previously only contained left (0) and right (1), indexing SwipeEdge.values with 2 caused a crash.

This PR adds SwipeEdge.none to represent EDGE_NONE, maps platform values explicitly in fromMap, and updates isButtonEvent accordingly. Unknown or out-of-range values are mapped to SwipeEdge.none rather than throwing a RangeError.

Decoupling split

Per the decoupling guidance, this PR is now scoped to framework/services changes only:

  • packages/flutter/lib/src/services/predictive_back_event.dart
  • packages/flutter/test/services/predictive_back_event_test.dart

Material widget tests and transition behavior tests have been removed from this PR and will be ported to material_ui once that package is ready to accept PRs.

A minimal one-line exhaustiveness update in predictive_back_page_transitions_builder.dart (SwipeEdge.none || null) is retained because adding the new enum value requires it for compilation.

Issues Fixed

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.

…eEdge index

Android can send a swipeEdge value of 2 (or other out-of-range values) which
caused a RangeError crash since SwipeEdge only has indices 0 (left) and 1
(right). Clamp the index to the valid range to handle unknown future values
gracefully.
@github-actions github-actions Bot added the framework flutter/packages/flutter repository. See also f: labels. label Apr 16, 2026
@google-cla

google-cla Bot commented Apr 16, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@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 modifies PredictiveBackEvent.fromMap to clamp the swipeEdge index to the valid range of SwipeEdge.values, preventing RangeError exceptions when receiving unexpected values from the platform. The test suite was updated to verify clamping behavior for negative and out-of-bounds indices. A review comment suggests casting the swipeEdge value to num before converting to int to improve robustness against platform-specific serialization differences.

muhammadkamel and others added 2 commits April 16, 2026 08:52
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@muhammadkamel
muhammadkamel force-pushed the fix/predictive-back-event-swipe-edge-out-of-bounds branch from 0f01f2d to 3304a67 Compare April 16, 2026 06:55
@muhammadkamel

Copy link
Copy Markdown
Contributor Author

Hi @Piinks,

Could you please review this PR? It fixes a RangeError crash in PredictiveBackEvent that occurs when the platform sends an out-of-range swipeEdge index on Android 13+.

I’ve implemented defensive clamping and added regression tests to ensure stability. I am hoping to get this landed as soon as possible so it can be included in the upcoming 3.44.0 stable release.

Thank you!

@github-actions github-actions Bot added the p: material_ui material_ui package in flutter/packages label Apr 16, 2026

@navaronbracke navaronbracke 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.

Just some remarks about aligning with the specification in the docs.

…ckEvent

On some Android 14+ devices, the platform sends swipeEdge=2
(BackEvent.EDGE_NONE) for button-triggered predictive back events,
causing a RangeError in PredictiveBackEvent.fromMap.

- Add SwipeEdge.none to the enum to explicitly represent EDGE_NONE
- Map swipeEdge int values explicitly (0→left, 1→right, 2→none,
  _→none) instead of indexing SwipeEdge.values directly
- Update isButtonEvent to return true when swipeEdge == SwipeEdge.none
- Expand test coverage to 100% of PredictiveBackEvent logic

Fixes: RangeError crash during predictive back on Android 14+
@muhammadkamel

Copy link
Copy Markdown
Contributor Author

@navaronbracke

I’ve made some changes to ensure alignment with the native documentation.

@muhammadkamel

Copy link
Copy Markdown
Contributor Author

Hi @justinmc
This PR should be merged ASAP as a hotfix.

@Piinks

Piinks commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

I am hoping to get this landed as soon as possible so it can be included in the upcoming 3.44.0 stable release.

This release has already been cut.

This PR should be merged ASAP as a hotfix.

Is there an open issue? If not please file one. We need to be able to evaluate the impact and risk before determining if we will hotfix something.

@justinmc justinmc 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.

Just some nits here.

@muhammadkamel Could you file an issue as suggested by @Piinks?

@muhammadkamel

Copy link
Copy Markdown
Contributor Author

@Piinks
@justinmc

I created an issue report for this PR: #186168

@muhammadkamel
muhammadkamel requested a review from justinmc May 7, 2026 13:20
justinmc
justinmc previously approved these changes May 8, 2026

@justinmc justinmc 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.

LGTM 👍 . Thank you for the thorough issue you created @muhammadkamel!

This PR will have to wait until after the code freeze unfortunately. I'll put it in draft mode and we'll come back to it.

@justinmc justinmc added the waiting for code freeze This PR is waiting for a code freeze to resolve. label May 8, 2026
@justinmc
justinmc marked this pull request as draft May 8, 2026 18:37
@maRci002

Copy link
Copy Markdown
Contributor

Same PR as #183642

@Piinks Piinks added the Decoupling: Not ready to port yet Instructions will be provided when this is ready to move to flutter/packages. label Jun 24, 2026
@Piinks

Piinks commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

I've marked this PR as not ready to port to flutter/packages yet.
We'll provide instructions to move this change over to material_ui once it is ready to receive PRs. Thank you!

The changes in the services library will remain here after.

@Piinks Piinks added the Decoupling: Split PR The PR will need to be split to separate Material & Cupertino changes label Jun 25, 2026
@Piinks

Piinks commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Advice for PR splitting: Since this touches material/cupertino along with other parts of flutter/flutter, it will need to be split up.

If the material/cupertino changes are dependent on the other non-material/cupertino changes in this PR, then the material/cupertino changes will need to wait for them to roll to stable before they can be ported over to material_ui/cupertino_ui in flutter/packages (which uses the stable branch).

  • If that is the case here, consider opening a new PR with the non-material/cupertino changes to move forward with so that waiting period can be reduced. Up to you!

@muhammadkamel

Copy link
Copy Markdown
Contributor Author

@Piinks I've split this PR per the decoupling guidance:

  • Framework/services changes remain here (predictive_back_event.dart + tests).
  • Material widget tests (right-edge swipe and button-triggered EDGE_NONE coverage) have been removed and will be ported to material_ui once that package is ready.
  • A minimal one-line exhaustiveness case for SwipeEdge.none is kept in predictive_back_page_transitions_builder.dart since the new enum value is required for compilation.

Happy to open the material_ui follow-up when instructions are available.

Remove Material widget tests and transition comments from this PR.
Those will be ported to material_ui once that package accepts PRs.

Keep the minimal SwipeEdge.none exhaustiveness case in the material
transition builder required for compilation after adding the enum value.
@Piinks

Piinks commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

Hey @muhammadkamel would you like to continue working on this PR? PRs marked as drafts are typically not reviewed, when you are ready, please mark it as ready for review.

@muhammadkamel
muhammadkamel marked this pull request as ready for review November 3, 2026 04:52
@github-actions

github-actions Bot commented Nov 3, 2026

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.

@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 predictive back page transitions to handle this new edge type, and adds comprehensive unit tests. Feedback is provided to simplify a redundant pattern in the swipeEdge switch expression.

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

The pattern 2 || _ is redundant because the wildcard pattern _ already matches any value, including 2. Simplifying this to just _ makes the code cleaner, more idiomatic, and avoids potential compiler warnings about redundant patterns.

Suggested change
swipeEdge: switch (map['swipeEdge']) {
0 => SwipeEdge.left,
1 => SwipeEdge.right,
2 || _ => SwipeEdge.none,
},
swipeEdge: switch (map['swipeEdge']) {
0 => SwipeEdge.left,
1 => SwipeEdge.right,
_ => SwipeEdge.none,
},
References
  1. Suggest simplification and refactoring to enhance readability and maintainability. (link)

@muhammadkamel

Copy link
Copy Markdown
Contributor Author

Thanks @Piinks, marked ready. One question on the code freeze check:

Adding SwipeEdge.none (Android's documented BackEvent.EDGE_NONE, API 36) requires a one-line exhaustiveness update in the frozen packages/flutter/lib/src/material/predictive_back_page_transitions_builder.dart, otherwise the framework doesn't compile. No behavior change there.

The material_ui side is already ported and approved: flutter/packages#12502 (its _ fallback handles none).

Can this compile-only change get a freeze exemption, or should the PR wait until Material is removed from the framework?

@Piinks

Piinks commented Nov 10, 2026

Copy link
Copy Markdown
Contributor

Can this compile-only change get a freeze exemption, or should the PR wait until Material is removed from the framework?

@justinmc can advise here thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Decoupling: Not ready to port yet Instructions will be provided when this is ready to move to flutter/packages. Decoupling: Split PR The PR will need to be split to separate Material & Cupertino changes framework flutter/packages/flutter repository. See also f: labels. p: material_ui material_ui package in flutter/packages waiting for code freeze This PR is waiting for a code freeze to resolve.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

5 participants