Skip to content

avoid_unsafe_collection_methods

v0.8.0 Warning Collection Type

This rule flags first, last, single and reduce used on a collection that has no emptiness check anywhere in the enclosing function.

All four throw a StateError on an empty iterable. Because the throw originates in dart:core, the stack trace points at framework code rather than the line that made the assumption — and the failure only appears once real data happens to be empty, which is usually in production rather than in tests.

Dart offers direct replacements: firstOrNull, lastOrNull and singleOrNull from package:collection, or fold instead of reduce when a seed value makes sense.

String firstName(List<User> users) {
// Throws when the list is empty
return users.first.name;
}
int total(List<int> amounts) {
return amounts.reduce((a, b) => a + b);
}
String? firstName(List<User> users) {
if (users.isEmpty) return null;
return users.first.name;
}
// Or use the null-returning variant
String? firstNameOrNull(List<User> users) {
return users.firstOrNull?.name;
}
// fold supplies a seed, so an empty list is fine
int total(List<int> amounts) {
return amounts.fold(0, (a, b) => a + b);
}

Detection is deliberately narrow, to keep false positives near zero:

  • Only a directly named receiver is checked — a local, parameter, or field. A chained expression like items.where(...).first has no name to match a guard against and is never reported.
  • Any emptiness check on that name anywhere in the function counts as a guard, even one in an unrelated branch. This over-accepts on purpose.
  • A collection literal with elements ([1, 2, 3].first) is treated as provably non-empty.
  • singleWhere is excluded: it throws when no element matches, which an emptiness check would not prevent.

This rule is in the opinionated preset, so it is on with preset: opinionated, or by name:

many_lints.yaml
rules:
avoid_unsafe_collection_methods: true

To turn it off again:

many_lints.yaml
rules:
avoid_unsafe_collection_methods: false

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