Skip to content

fix: prevent crash when tapping editor with empty document - #1245

Open
akhilk49 wants to merge 1 commit into
AppFlowy-IO:mainfrom
akhilk49:fix/empty-document-selection-crash-1218
Open

akhilk49 wants to merge 1 commit into
AppFlowy-IO:mainfrom
akhilk49:fix/empty-document-selection-crash-1218

Conversation

@akhilk49

Copy link
Copy Markdown

Fixes #1218

Problem

When an empty document (Document.blank(withInitialText: false)) is rendered and the editor surface is tapped on mobile, the app crashes with a RangeError / Invalid argument(s) exception.

Root Cause

The mobile selection service calls editorState.getNodeInOffset(sortedNodes, offset, 0, sortedNodes.length - 1). When the document is empty, sortedNodes is [] and end becomes -1.

The guard in shared.dart used && instead of ||:

dart // Before (buggy) if (start < 0 && end >= sortedNodes.length) { return null; }

For the empty-list case (start=0, end=-1, length=0), this evaluates to alse && true = false, so the code continues and indexes into an empty list in _findCloseNode, raising a RangeError.

The desktop selection service already had an isEmpty early-return guard, but the mobile service did not.

Fix

lib/src/editor/editor_component/service/selection/shared.dart — replaced the && guard with a comprehensive bounds check that handles empty lists, negative indices, inverted ranges, and out-of-bounds values:

dart if (sortedNodes.isEmpty || start < 0 || end < 0 || start > end || start >= sortedNodes.length || end >= sortedNodes.length) { return null; }

lib/src/editor/editor_component/service/selection/mobile_selection_service.dart — added an isEmpty early-return guard matching the existing pattern in desktop_selection_service.dart (defense-in-depth).

Testing

Added est/editor/editor_component/service/selection/shared_selection_empty_document_test.dart with 4 regression tests:

  1. getNodeInOffset([], offset, 0, -1) — the exact mobile call path
  2. getNodeInOffset([], offset, -1, -1) — fully negative range
  3. getNodeInOffset([], offset, 0, 100) — out-of-bounds end
  4. Widget test through MobileSelectionServiceWidget with an empty document

All 67 tests in est/editor/ pass, including the 4 new tests.

Reproduction evidence

Before the fix, running the regression test produced:
RangeError (length): Invalid value: Valid value range is empty: -1 at shared.dart:173 (_findCloseNode) at shared.dart:46 (getNodeInOffset)

After the fix, all tests pass with no exceptions.

…IO#1218)

When an empty document (Document.blank(withInitialText: false)) is
rendered and the editor surface is tapped, the mobile selection
service calls getNodeInOffset with an empty node list and end=-1.

The guard in shared.dart used && instead of ||, so it only returned
null when BOTH start<0 AND end>=length were true. For the empty-list
case (start=0, end=-1), the condition was false, and the code
proceeded to index into an empty list, raising a RangeError.

Fix:
- shared.dart: replace the && guard with a comprehensive bounds check
  that handles empty lists, negative indices, and start>end.
- mobile_selection_service.dart: add an isEmpty early-return guard,
  matching the existing pattern in desktop_selection_service.dart.

Added regression tests covering all three edge cases plus a widget
test through MobileSelectionServiceWidget.
@CLAassistant

CLAassistant commented Oct 28, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ArgumentError in _findCloseNode when tapping an empty EditorState

2 participants