`ArgumentError` in `_findCloseNode` when tapping an empty EditorState

Open Beginner friendly
#1,218 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
84/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
dart, flutter
Domain
frontend

Research direction

Start in lib/src/editor/editor_component/service/selection/shared.dart, focusing on getNodeInOffset and its call to _findCloseNode. Reproduce the tap with Document.blank(withInitialText: false), then verify the empty-node case returns null and the editor no longer throws an ArgumentError during selection handling.

Written by the indexing model from the issue text.

Description

Describe the bug

When EditorState is initialized with a completely empty Document (i.e. containing 0 nodes, such as Document.blank(withInitialText: false)) and the user taps inside the editor, an ArgumentError: Invalid argument(s): 0 is thrown by _findCloseNode in shared.dart.

Steps to Reproduce
  1. Initialize EditorState with Document.blank(withInitialText: false).
  2. Render AppFlowyEditor.
  3. Tap on the editor surface.
  4. The application throws the following exception:
ArgumentError: Invalid argument(s): 0

Stack trace:
EditorStateSelection._findCloseNode
EditorStateSelection.getNodeInOffset
_MobileSelectionServiceWidgetState.getNodeInOffset
_MobileSelectionServiceWidgetState.getPositionInOffset
_MobileSelectionServiceWidgetState._onTapUpAndroid
Expected Behavior

The editor should handle the empty node list gracefully without throwing an exception, likely by returning null from getNodeInOffset and safely ignoring the tap selection.

Root Cause Analysis

In lib/src/editor/editor_component/service/selection/shared.dart, the getNodeInOffset function attempts to guard against invalid bounds:

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

If sortedNodes is empty, getNodeInOffset receives start = 0 and end = -1.
The condition end >= sortedNodes.length evaluates to -1 >= 0, which is false. Because of the && operator, the bounds check fails to catch the empty array case.

The code then proceeds to call _findCloseNode(sortedNodes, 0, -1).
Inside _findCloseNode, the binary search loop is skipped, and it returns:

    return min.clamp(start, end);

Since min = 0, start = 0, and end = -1, 0.clamp(0, -1) throws an ArgumentError: Invalid argument(s): 0 because the lower bound is greater than the upper bound.

Proposed Fix

Change the bounds check in getNodeInOffset to:

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

Or alternatively, add an explicit check for empty lists:

    if (sortedNodes.isEmpty) return null;
Dominant language
Dart
Stars
684
Forks
330
PR merge metrics
No merged PRs in 30d

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from AppFlowy-IO/appflowy-editor

All issues in AppFlowy-IO/appflowy-editor

Similar issues

More Dart issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.