LlmChatView dispose() does not cancel pending streaming response, causing setState on disposed widget
Nobody has claimed this yet.
Assessment
- Difficulty
- 1/5
- Estimated time
- Under an hour
- Newbie friendliness
- 70/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Quiet
- Tech stack
- dart, flutter
- Domain
- mobile-dev
Research direction
Start in llm_chat_view.dart at _LlmChatViewState.dispose() and compare its lifecycle handling with _onCancelMessage(), which already uses LlmResponse.cancel(). Reproduce navigation away during streaming, then verify that the pending response no longer reaches the update callback or triggers setState after disposal.
Written by the indexing model from the issue text.
Description
Description
_LlmChatViewState.dispose() does not cancel _pendingPromptResponse, causing a Null check operator used on a null value crash when the user navigates away from the chat while the AI is still streaming a response.
Steps to Reproduce
- Open a chat with an LLM using
LlmChatView - Send a message that triggers a streaming response
- Navigate away (pop the page) before the response finishes streaming
Error
_TypeError: Null check operator used on a null value
Stack trace:
State.setState (package:flutter/src/widgets/framework.dart:1219)
_LlmChatViewState._onSendMessage.<fn> (package:flutter_ai_toolkit/src/views/llm_chat_view/llm_chat_view.dart:257)
FirebaseProvider._sendMessageStream (package:flutter_ai_toolkit/src/providers/implementations/firebase_provider.dart)
Root Cause
In llm_chat_view.dart, the _onSendMessage method creates an LlmResponse with an onUpdate callback that calls setState:
// line 253-258
_pendingPromptResponse = LlmResponse(
stream: sendMessageStream(prompt, attachments: attachments),
onUpdate: (_) => setState(() {}),
onDone: _onPromptDone,
);
But dispose() (line 174) does not cancel this response:
@override
void dispose() {
super.dispose();
widget.viewModel.provider.removeListener(_onHistoryChanged);
}
When the widget is disposed while streaming is active, the LlmResponse subscription continues to receive data and calls setState on the disposed state, crashing at _element! inside State.setState.
Suggested Fix
Cancel the pending response in dispose():
@override
void dispose() {
_pendingPromptResponse?.cancel();
super.dispose();
widget.viewModel.provider.removeListener(_onHistoryChanged);
}
The cancel() method already exists on LlmResponse and is used by _onCancelMessage() — it just needs to also be called during disposal.
Impact
- 588 occurrences across 124 users in our production app (CraftNote)
- Affects any app using
LlmChatViewwhere users can navigate away during streaming - Package version:
flutter_ai_toolkit 1.0.0
Environment
- Flutter AI Toolkit: 1.0.0
- Flutter: 3.27+
- Platform: iOS (but likely affects all platforms)
- Dominant language
- Dart
- Stars
- 287
- Forks
- 94
- PR merge metrics
- No merged PRs in 30d
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from flutter/ai
-
Difficulty 2/5 1-3 hours Newbie friendliness 64/100
-
Loan app Open
Difficulty 5/5 Over a week Newbie friendliness 15/100
-
IDX -> Antigravitiy Open
-
Difficulty 5/5 Over a week Newbie friendliness 25/100
-
waiting for customer response
Difficulty 5/5 Over a week Newbie friendliness 30/100
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
code quality good first issue
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Suwayomi/Suwayomi-Tsumiru#479 ·
-
Build Failure: agora_rtc_engine compiled against android-31 while dependencies require android-34+ Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 92/100
conceptadev/noir#95 ·