Async Await Null Race Condition
SkillMediaFix "Null check operator used on a null value" errors when an object is set to null during an async await. Use when: (1) Object reference is nullified while awaiting, (2) Code accesses object with ! after await returns, (3) Cancel/dispose operations run concurrently with async operations on same object. Solution: capture local reference before await.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Async Await Null Race Condition skill
What this skill tells your AI
The instructions your AI receives, as published by divinevideo/divine-mobile in .agents/skills/async-await-null-race-condition/SKILL.md and read by ahel’s review.
Problem
When an async operation is awaiting, external code can set the object reference to null.
When the await completes, accessing the object with ! throws "Null check operator
used on a null value".
Context / Trigger Conditions
- Error:
Null check operator used on a null value - Pattern:
await someObject!.asyncMethod()followed bysomeObject!.property - Object can be nullified by cancel/dispose/cleanup operations
- Concurrent operations on shared mutable state
- Typically seen with session objects, connection handlers, or service references
Solution
Wrong - Object can become null during await:
Future<Result> waitForResponse() async {
// _session might be set to null while we're awaiting
final result = await _session!.waitForConnection();
if (result == null) {
// BUG: _session could be null here!
final state = _session!.state; // Throws null check error
...
}
}
void cancel() {
_session?.cancel();
_session = null; // This runs while waitForResponse is awaiting
}
Correct - Capture local reference before await:
Future<Result> waitForResponse() async {
// Capture reference BEFORE await
final session = _session!;
final result = await session.waitForConnection();
// Check if cancelled during await
if (_session == null) {
return Result.cancelled();
}
if (result == null) {
// Safe - using captured local reference
final state = session.state;
...
}
}
Verification
- Trigger the cancel/dispose operation while async operation is in progress
- No null check errors should occur
- Operation should gracefully handle cancellation
Example - Full Pattern
class ConnectionManager {
Session? _session;
Future<ConnectionResult> connect() async {
if (_session == null) {
return ConnectionResult.failure('No session');
}
// Capture before await
final session = _session!;
final response = await session.waitForResponse(
timeout: Duration(minutes: 2),
);
// Check if cancelled during await
if (_session == null) {
return ConnectionResult.failure('Cancelled');
}
// Safe to use captured reference
if (response == null) {
return ConnectionResult.failure(session.errorMessage);
}
return ConnectionResult.success(response);
}
void cancel() {
_session?.cancel();
_session?.dispose();
_session = null;
}
}
Notes
- This pattern applies to any mutable reference that can be nullified externally
- Common in Flutter/Dart with dispose patterns, Riverpod providers, and WebSocket sessions
- The captured local reference keeps the object alive during the await
- Always add a null check after await to detect cancellation
- Consider using
Completercancellation patterns for more complex scenarios
Related Patterns
riverpod-ref-read-in-dispose- Similar issue with Riverpod ref lifecycleflutter-dispose-timer-test-failure- Timer callbacks after disposal
Signals
- GitHub stars
- 265
- Forks
- 55
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
async-await-null-race-condition- Source
- github.com/divinevideo/divine-mobile