Skip to content
Back to skills

Async Await Null Race Condition

ASecurity

Fix "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.

  • 265 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 3, 2026
development

Works with

  • claude code

Security analysis

A100/100

Scanned September 3, 2026

npx -y skills add divinevideo/divine-mobile --skill async-await-null-race-condition --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Async Await Null Race Condition?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Async Await Null Race Condition
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/divinevideo-async-await-null-race-condition-divine-mobile/badge)](https://www.skillsdirectory.com/skills/divinevideo-async-await-null-race-condition-divine-mobile)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: async-await-null-race-condition
description: |
  Fix "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.
author: Claude Code
version: 1.0.0
date: 2026-02-01
---

# Async Await Null Race Condition

## 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 by `someObject!.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:
```dart
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:
```dart
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
1. Trigger the cancel/dispose operation while async operation is in progress
2. No null check errors should occur
3. Operation should gracefully handle cancellation

## Example - Full Pattern

```dart
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 `Completer` cancellation patterns for more complex scenarios

## Related Patterns
- `riverpod-ref-read-in-dispose` - Similar issue with Riverpod ref lifecycle
- `flutter-dispose-timer-test-failure` - Timer callbacks after disposal

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…