Skip to content

avoid_late_final_reassignment

v1.0.0 Warning Resource Management

This rule flags a late final field assigned more than once on the same straight-line path.

This rule is in the core preset.

late final promises one assignment, and Dart enforces it — but at run time, by throwing LateInitializationError on the second write. A second assignment the analyzer can see on one path is therefore a guaranteed crash, not a possibility, and it is worth catching before the code runs.

See also: late variables

Assigning a provisional value and then refining it. The second line throws:

class Session {
late final String token;
void start(String value) {
token = value;
token = value.trim(); // throws LateInitializationError
}
}

Compute the final value first, then assign once:

class Session {
late final String token;
void start(String value) {
token = value.trim();
}
}

Two writes in opposite arms of an if are exactly what late final is for — only one of them ever runs, so this is not reported:

class Session {
late final String token;
void start({required bool isGuest}) {
if (isGuest) {
token = 'guest';
} else {
token = _generate();
}
}
String _generate() => 'real';
}

The same holds for a switch, and for an early return:

class Session {
late final String token;
void start(String? cached) {
if (cached != null) {
token = cached;
return;
}
token = _generate();
}
String _generate() => 'real';
}

Only writes in the same block are compared, and the rule does not follow branches. That is what makes the branching examples above pass — but it also means a genuine double write split across a branch boundary is missed:

void start(String value) {
if (value.isNotEmpty) {
token = value; // not reported
}
token = value.trim(); // throws at run time when the branch above ran
}

Only fields are checked. A late final local with the same defect is left to the analyzer, which already flags it at compile time.

Only a plain = counts; a compound assignment to a late final does not compile in the first place.

To disable this rule:

many_lints.yaml
rules:
avoid_late_final_reassignment: false

To keep the rule on but skip certain paths, use per-rule exclude.