@tduncan / Cortana / commits / 2c56b51

fix(core): ignore benign SelectionContainer concurrent modification error #90

abdulmominsakib committed Sep 21, 2026 at 09:43 UTC 2c56b5169673357968ac5379c99fd494fa3d9529
2 files changed +37
lib/core/services/crash_report_service.dart
+25
@@ -233,6 +233,10 @@ class CrashReportService {
233 errorWidgetPayload: errorWidgetPayload,
234 );
235
236 + if (isBenignFrameworkError(error, stack)) {
237 + return report;
238 + }
239 +
240 // The duplicate check must run before the report is recorded, otherwise
241 // the freshly added report matches itself and no crash would ever surface
242 // in the UI.
@@ -249,6 +253,27 @@ class CrashReportService {
253 return report;
254 }
255
256 + /// Checks whether an error is a known non-fatal Flutter framework issue that
257 + /// should not crash the app or show the crash fallback screen.
258 + ///
259 + /// Currently handled:
260 + /// - flutter/flutter#192081: Concurrent modification during iteration in
261 + /// `MultiSelectableSelectionContainerDelegate.handleClearSelection` when
262 + /// clearing selection across scrollable elements (e.g. Markdown code blocks).
263 + static bool isBenignFrameworkError(Object error, [StackTrace? stack]) {
264 + final errorStr = error.toString();
265 + final stackStr = stack?.toString() ?? '';
266 +
267 + if (errorStr.contains('Concurrent modification during iteration') &&
268 + (stackStr.contains('MultiSelectableSelectionContainerDelegate') ||
269 + stackStr.contains('selectable_region.dart') ||
270 + stackStr.contains('_ScrollableSelectionContainerDelegate'))) {
271 + return true;
272 + }
273 +
274 + return false;
275 + }
276 +
277 /// Clear the current crash so the app can re-render normally.
278 void clearCrash() {
279 _setCurrentCrash(null);
lib/main.dart
+12
@@ -23,6 +23,12 @@ Future<void> main() async {
23 // window, so the user sees only one crash screen per incident.
24 FlutterError.onError = (details) {
25 FlutterError.presentError(details);
26 + if (CrashReportService.isBenignFrameworkError(
27 + details.exception,
28 + details.stack,
29 + )) {
30 + return;
31 + }
32 crashReports.capture(
33 details.exception,
34 details.stack ?? StackTrace.current,
@@ -31,6 +37,9 @@ Future<void> main() async {
37 };
38
39 PlatformDispatcher.instance.onError = (error, stack) {
40 + if (CrashReportService.isBenignFrameworkError(error, stack)) {
41 + return true;
42 + }
43 crashReports.capture(error, stack);
44 return true;
45 };
@@ -53,6 +62,9 @@ Future<void> main() async {
62 runApp(const CrashFallbackApp());
63 },
64 (error, stack) {
65 + if (CrashReportService.isBenignFrameworkError(error, stack)) {
66 + return;
67 + }
68 CrashReportService.instance.capture(error, stack);
69 },
70 );