Skip to content

Fix ParallelWaitError in forEachIsolateHelper during service disconnect - #10074

Merged
srawlins merged 1 commit into
flutter:masterfrom
srawlins:parallel-wait
Nov 4, 2026
Merged

srawlins merged 1 commit into
flutter:masterfrom
srawlins:parallel-wait

Conversation

@srawlins

@srawlins srawlins commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

forEachIsolateHelper used [for (final isolate in vmIsolates) callback(isolate)].wait. In Dart 3, the Iterable.wait extension wraps any error from completed futures in a ParallelWaitError<V, E>.

When a target application exits or a VM Service connection is shut down while an operation is in flight (e.g. periodic polling in refreshNetworkData), VM Service methods like getSocketProfileWrapper throw RPCError: (112) Service has disappeared. Callers catch typed errors (e.g., on RPCError catch (e) in network_service.dart or on SentinelException / on RPCError in service_extension_manager.dart) and check e.isServiceDisposedError to safely swallow teardown exceptions.

Because ParallelWaitError does not inherit from RPCError or Exception, it bypassed these typed catch blocks and escaped uncaught, causing flaky integration test failures in network_screen_test.dart. See this log.

Using Future.wait preserves the underlying exception type thrown by the isolate callback. Also update _enableNetworkTrafficRecordingOnAllIsolates to use Future.wait.

`forEachIsolateHelper` used `[for (final isolate in vmIsolates) callback(isolate)].wait`.
In Dart 3, the `Iterable.wait` extension wraps any error from completed futures
in a `ParallelWaitError<V, E>`.

When a target application exits or a VM Service connection is shut down while an
operation is in flight (e.g. periodic polling in `refreshNetworkData`), VM Service
methods like `getSocketProfileWrapper` throw `RPCError: (112) Service has disappeared`.
Callers catch typed errors (e.g., `on RPCError catch (e)` in `network_service.dart` or
`on SentinelException` / `on RPCError` in `service_extension_manager.dart`) and check
`e.isServiceDisposedError` to safely swallow teardown exceptions.

Because `ParallelWaitError` does not inherit from `RPCError` or `Exception`, it bypassed
these typed catch blocks and escaped uncaught, causing flaky integration test failures
in `network_screen_test.dart`.

Using `Future.wait` preserves the underlying exception type thrown by the isolate
callback. Also update `_enableNetworkTrafficRecordingOnAllIsolates` to use `Future.wait`.

@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 replaces the use of the .wait extension on lists of futures with Future.wait in _enableNetworkTrafficRecordingOnAllIsolates and forEachIsolateHelper. This ensures that isolate callback exceptions (such as RPCError or SentinelException) are rethrown directly instead of being wrapped in a ParallelWaitError. Unit tests have been added to verify this behavior, and the changelog has been updated. I have no feedback to provide on these changes.

@srawlins
srawlins merged commit e18fd8e into flutter:master Nov 4, 2026
51 of 52 checks passed
@srawlins
srawlins deleted the parallel-wait branch November 4, 2026 00:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants