Skip to main content

require-atomic-async-updates

effort: 3m
pro+

Warns when an assignment can lead to a race condition due to await.

An assignment is reported when the rule detects the following execution flow in an async function:

  1. The variable is read.
  2. An await pauses the function.
  3. After the function is resumed, a value is assigned to the variable from step 1.

The assignment in step 3 is reported because it may be incorrectly resolved because the value of the variable from step 1 may have changed between steps 2 and 3. In particular, if the variable can be accessed from other execution contexts (for example, if it is not a local variable and therefore other functions can change it), the value of the variable may have changed elsewhere while the function was paused in step 2.

Example

❌ Bad:

int foo = 0;

Future<void> fn(Future<int> amount) async {
// LINT: This reassignment might use an outdated value due to a race condition.
// Consider moving the await expression to its own local variable.
foo += await amount;
// LINT: This reassignment might use an outdated value due to a race condition.
// Consider moving the await expression to its own local variable.
foo = foo + await amount;
}

void main() {
Future.wait([fn(...), fn(...)]); // "fn" is called more than once
}

✅ Good:

int foo = 0;

Future<void> fn(Future<int> amount) async {
final local = await amount;
foo += local;
}