@tduncan / Cortana / commits / 007c8fa

fix(core): ignore benign SelectionContainer RangeError #101

Treat a RangeError raised from Flutter's selection delegate as a non-fatal framework error, like the concurrent-modification case. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

abdulmominsakib committed Sep 28, 2026 at 09:44 UTC 007c8fa1935ff15862c3dc9e04e2e90c1a098738
2 files changed +47 -3
lib/core/services/crash_report_service.dart
+12 -3
@@ -260,14 +260,23 @@ class CrashReportService {
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 + /// - A stale-index `RangeError` in
264 + /// `MultiSelectableSelectionContainerDelegate.getSelectionGeometry` when
265 + /// selectables change while a selection edge is being updated.
266 static bool isBenignFrameworkError(Object error, [StackTrace? stack]) {
267 final errorStr = error.toString();
268 final stackStr = stack?.toString() ?? '';
269 + final isSelectionStack =
270 + stackStr.contains('MultiSelectableSelectionContainerDelegate') ||
271 + stackStr.contains('selectable_region.dart') ||
272 + stackStr.contains('_ScrollableSelectionContainerDelegate');
273
274 if (errorStr.contains('Concurrent modification during iteration') &&
268 - (stackStr.contains('MultiSelectableSelectionContainerDelegate') ||
269 - stackStr.contains('selectable_region.dart') ||
270 - stackStr.contains('_ScrollableSelectionContainerDelegate'))) {
275 + isSelectionStack) {
276 + return true;
277 + }
278 +
279 + if (error is RangeError && isSelectionStack) {
280 return true;
281 }
282
test/core/services/crash_report_service_test.dart
+35
@@ -179,4 +179,39 @@ void main() {
179 expect(service.currentCrash.value, isNull);
180 });
181 });
182 +
183 + group('CrashReportService.isBenignFrameworkError', () {
184 + final selectionStack = StackTrace.fromString(
185 + '#0 List.[] (dart:core-patch/growable_array.dart)\n'
186 + '#1 MultiSelectableSelectionContainerDelegate.getSelectionGeometry '
187 + '(package:flutter/src/widgets/selectable_region.dart:2643)\n',
188 + );
189 +
190 + test('ignores selection RangeError (#101)', () {
191 + final error = RangeError.index(3, [1, 2, 3], 'length');
192 + expect(
193 + CrashReportService.isBenignFrameworkError(error, selectionStack),
194 + isTrue,
195 + );
196 + });
197 +
198 + test('ignores selection concurrent modification (#99)', () {
199 + final error = ConcurrentModificationError(<int>[]);
200 + expect(
201 + CrashReportService.isBenignFrameworkError(error, selectionStack),
202 + isTrue,
203 + );
204 + });
205 +
206 + test('reports RangeError outside selection code', () {
207 + final error = RangeError.index(3, [1, 2, 3], 'length');
208 + expect(
209 + CrashReportService.isBenignFrameworkError(
210 + error,
211 + StackTrace.fromString('#0 main (package:localmind/main.dart)'),
212 + ),
213 + isFalse,
214 + );
215 + });
216 + });
217 }