avoid-unsafe-collection-methods

Path
lint/correctness/avoid-unsafe-collection-methods
Default
Off, opt in
Origin
Falcon
Rule
180 of 512

Flags potentially throwing element access on SDK collections.

Iterable first/last/single (including object-pattern getters), predicate searches without an orElse fallback, elementAt, and List indexing can throw when an element does not exist. The max/min extension getters are included only when their resolved extension comes from package:collection. Prefer nullable alternatives. Map indexing, unknown receivers, and custom collection implementations are excluded. List indexing is safe in a resolved Flutter ListView.builder/GridView.builder's direct, synchronous itemBuilder body when itemCount is the same local list's length (including list?.length ?? 0) and the index is its second parameter. Both bindings must be unreassigned. The list must otherwise appear only as an index or length receiver: aliases, helper arguments, method calls, setters and cascades conservatively disable the exemption. Shadowed bindings and nested callbacks do not inherit it. Other bounds/cardinality proofs are not attempted.

Invalid

example.dartdart
import 'package:collection/collection.dart';

void access(List<int> values, Set<String> names, Iterable<int> items, int index) {
  print(values.first);
  print(names.last);
  print(items.single);
  print(values[index]);
  print(items.elementAt(index));
  print(values.firstWhere((value) => value > 0));
  print(values.lastWhere((value) => value > 0));
  print(values.singleWhere((value) => value > 0));
  values..first;
  values..firstWhere((value) => value > 0);
}

void objectPatterns(Object value) {
  if (value case List<int>(first: final first)) {
    print(first);
  }
  if (value case Iterable<int>(last: final last)) {
    print(last);
  }
  if (value case Set<int>(single: final single)) {
    print(single);
  }
}

void packageExtrema(Iterable<int> values) {
  print(values.max);
  print(values.min);
  values..max;
  if (values case Iterable<int>(min: final smallest)) {
    print(smallest);
  }
}

class NotString {
  List<int> split(String separator) => [];
}

void customSplit(NotString value) {
  print(value.split(',').first);
  print(value.split(',').last);
}

void mutatedSplit(String text) {
  text.split(',')..clear()..first;
}

void splitResults(String text, Pattern separator) {
  print(text.split(separator).first);
  print(text.split(separator).last);
  text.split(separator)..first..last;
  print(''.split('').first);
  print(''.split(RegExp('')).last);
}
Collection access may throw — use a nullable lookup or an explicit fallback.
3void access(List<int> values, Set<String> names, Iterable<int> items, int index) {
4 print(values.first);
Collection access may throw — use a nullable lookup or an explicit fallback.
4 print(values.first);
5 print(names.last);
Collection access may throw — use a nullable lookup or an explicit fallback.
5 print(names.last);
6 print(items.single);
Collection access may throw — use a nullable lookup or an explicit fallback.
6 print(items.single);
7 print(values[index]);
Collection access may throw — use a nullable lookup or an explicit fallback.
7 print(values[index]);
8 print(items.elementAt(index));
Collection access may throw — use a nullable lookup or an explicit fallback.
8 print(items.elementAt(index));
9 print(values.firstWhere((value) => value > 0));
Collection access may throw — use a nullable lookup or an explicit fallback.
9 print(values.firstWhere((value) => value > 0));
10 print(values.lastWhere((value) => value > 0));
Collection access may throw — use a nullable lookup or an explicit fallback.
10 print(values.lastWhere((value) => value > 0));
11 print(values.singleWhere((value) => value > 0));
Collection access may throw — use a nullable lookup or an explicit fallback.
11 print(values.singleWhere((value) => value > 0));
12 values..first;
Collection access may throw — use a nullable lookup or an explicit fallback.
12 values..first;
13 values..firstWhere((value) => value > 0);
Collection access may throw — use a nullable lookup or an explicit fallback.
16void objectPatterns(Object value) {
17 if (value case List<int>(first: final first)) {
Collection access may throw — use a nullable lookup or an explicit fallback.
19 }
20 if (value case Iterable<int>(last: final last)) {
Collection access may throw — use a nullable lookup or an explicit fallback.
22 }
23 if (value case Set<int>(single: final single)) {
Collection access may throw — use a nullable lookup or an explicit fallback.
28void packageExtrema(Iterable<int> values) {
29 print(values.max);
Collection access may throw — use a nullable lookup or an explicit fallback.
29 print(values.max);
30 print(values.min);
Collection access may throw — use a nullable lookup or an explicit fallback.
30 print(values.min);
31 values..max;
Collection access may throw — use a nullable lookup or an explicit fallback.
31 values..max;
32 if (values case Iterable<int>(min: final smallest)) {
Collection access may throw — use a nullable lookup or an explicit fallback.
41void customSplit(NotString value) {
42 print(value.split(',').first);
Collection access may throw — use a nullable lookup or an explicit fallback.
42 print(value.split(',').first);
43 print(value.split(',').last);
Collection access may throw — use a nullable lookup or an explicit fallback.
46void mutatedSplit(String text) {
47 text.split(',')..clear()..first;
Collection access may throw — use a nullable lookup or an explicit fallback.
50void splitResults(String text, Pattern separator) {
51 print(text.split(separator).first);
Collection access may throw — use a nullable lookup or an explicit fallback.
51 print(text.split(separator).first);
52 print(text.split(separator).last);
Collection access may throw — use a nullable lookup or an explicit fallback.
52 print(text.split(separator).last);
53 text.split(separator)..first..last;
Collection access may throw — use a nullable lookup or an explicit fallback.
52 print(text.split(separator).last);
53 text.split(separator)..first..last;
Collection access may throw — use a nullable lookup or an explicit fallback.
53 text.split(separator)..first..last;
54 print(''.split('').first);
Collection access may throw — use a nullable lookup or an explicit fallback.
54 print(''.split('').first);
55 print(''.split(RegExp('')).last);

Valid

example.dartdart
void access(List<int> values, Map<int, String> names, dynamic unknown) {
  print(names[0]);
  print(values.firstOrNull);
  print(values.lastOrNull);
  print(values.singleOrNull);
  print(values.firstWhere((value) => value > 0, orElse: () => 0));
  print(values.lastWhere((value) => value > 0, orElse: () => 0));
  print(values.singleWhere((value) => value > 0, orElse: () => 0));
  print(unknown.first);
}
class Custom {
  int get first => 0;
  int operator [](int index) => 0;
}
void custom(Custom value) { print(value.first); print(value[0]); }


class Splittable {
  Custom split(String separator) => Custom();
}

void customSplit(Splittable value) {
  print(value.split(',').first);
}

void customPatterns(Object value) {
  if (value case Custom(first: final first)) {
    print(first);
  }
}

extension LocalExtrema on Iterable<int> {
  int get max => 0;
  int get min => 0;
}

void localExtrema(Iterable<int> values) {
  print(values.max);
  print(values.min);
  if (values case Iterable<int>(max: final maximum)) {
    print(maximum);
  }
}

Configure avoid-unsafe-collection-methods

Set its severity in falcon.json. See the configuration guide.

falcon.jsonjson
{
  "linter": {
    "rules": {
      "correctness": {
        "avoid-unsafe-collection-methods": "error"
      }
    }
  }
}

Or silence one occurrence with a suppression comment; the reason is required.

example.dartdart
// falcon-ignore lint/correctness/avoid-unsafe-collection-methods: <reason>
  • avoid-unsafe-reduce

    Warn when SDK Iterable.reduce can receive an empty collection.

  • avoid-unused-after-null-check

    Reports a null-checked local ignored by a branch that passes another local of the same resolved type to a call.

  • avoid-unused-parametersavoid-unused-parametersrecommended

    Disallow declared parameters that are never used, excluding primary constructors.

  • avoid-watch-outside-buildrecommendedprovider

    Flags listening Provider accesses proven to run outside Flutter builds.

  • avoid-web-libraries-in-flutteravoid_web_libraries_in_flutterrecommendedflutter

    Disallow importing web-only dart: libraries from Flutter code.

  • await-only-futuresawait_only_futuresrecommended

    Await only values assignable to futures; FutureOr, dynamic, bottom types and extension types are accepted like the analyzer.

  • banned-importscross-file

    Report imports forbidden by package-relative architectural boundaries.

  • cancel-subscriptionscancel_subscriptionsrecommended

    Cancel instances of dart:async StreamSubscription.