Skip to content

QuillRawEditorState crashes when post-frame focus callback runs after widget is disposed #2737

Description

@hardiklakhalani

Have you checked for an existing issue?

Flutter Quill Version

11.5.1

Steps to Reproduce

  1. Embed QuillEditor in a widget tree that temporarily changes the editor’s parent structure during async work (e.g. toggling between QuillEditor and IgnorePointer(child: QuillEditor) while loading).
  2. Trigger a focus/selection change during or after that rebuild (e.g. programmatic replaceText / selection update when async work completes).
  3. Observe a scheduler callback exception in _handleFocusChanged post-frame closure.

Expected results

Deferred focus/keyboard work should no-op safely if the editor state is no longer mounted.

Actual results

Post-frame callback runs on a disposed QuillRawEditorState and crashes when resolving keyboard appearance via context.

Additional Context

Details

Root cause

When dirty is true, _handleFocusChanged calls requestKeyboard() immediately and schedules _handleFocusChanged again via addPostFrameCallback without checking mounted. Other paths in the same file (e.g. _showCaretOnScreen) already guard with if (!mounted) return;; this path does not.

Proposed fix

  • Guard _handleFocusChanged with if (!mounted) return; at entry.
  • Guard the post-frame callback before re-entering _handleFocusChanged.
  • Add early mounted checks in requestKeyboard() and/or openConnectionIfNeeded() for defense in depth.

Impact

  • Prevents background FlutterErrors / Crashlytics noise when editors are rebuilt or disposed during focus/selection updates.
  • No intended change to normal typing, focus, or keyboard behavior when the widget remains mounted.
Stack trace: State.context ← RawEditorStateTextInputClientMixin.createKeyboardAppearance ← RawEditorStateTextInputClientMixin.openConnectionIfNeeded ← QuillRawEditorState.requestKeyboard ← QuillRawEditorState._handleFocusChanged ← QuillRawEditorState._handleFocusChanged. (post-frame callback) ← SchedulerBinding.handleDrawFrame

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions