avoid_catch_error
v1.0.0 Warning Async Safety
This rule flags calls to Future.catchError. The same error handling is expressed more safely with await inside a try/catch block.
Why use this rule
Section titled “Why use this rule”catchError accepts a plain Function, not a typed callback. The analyzer therefore cannot check the handler’s signature at all: passing a callback that takes the wrong number of parameters compiles cleanly and throws ArgumentError at runtime — and only on the error path, which is the path least likely to be exercised by a test.
The test parameter adds a second trap. When it returns false the error is not handled; it flows on to the next handler or to the zone’s error handler, even though the code reads as though the error was caught.
try/catch avoids both problems. The catch clause’s parameters are checked at compile time, the control flow is explicit, and on SomeError catch (e) expresses the filtering that test was doing.
See also: Future.catchError API docs, Dart: asynchronous programming, Effective Dart: avoid using Future.catchError
// The handler's signature is unchecked — an arity mistake here throws// at runtime, not at compile time.Future<int> load() { return repository.fetch().catchError((err, st) { log(err, st); return 0; });}Future<int> load() async { try { return await repository.fetch(); } catch (err, st) { log(err, st); return 0; }}Filtering by error type becomes an on clause:
Future<int> load() async { try { return await repository.fetch(); } on TimeoutException catch (err, st) { log(err, st); return 0; }}Known limitations
Section titled “Known limitations”Only invocations are reported. A tear-off such as future.catchError is left alone, since there is no call site to rewrite.
The receiver must resolve to a Future (or a subtype), so an unrelated user-defined catchError method is never flagged. If the receiver’s type cannot be resolved, the rule stays silent.
Configuration
Section titled “Configuration”This rule is in the opinionated preset. With a lower preset, enable it by
name with avoid_catch_error: true.
To turn it off:
rules: avoid_catch_error: falseTo keep the rule on but skip certain paths, use per-rule exclude.
Related rules
Section titled “Related rules”avoid_future_ignore— Do not silently suppress Future errors with an unexplained ignore call.avoid_missing_completer_stack_trace— Pass the stack trace to Completer.completeError.avoid_nested_futures— Don’t declare Future<Future<T>>.avoid_passing_async_when_sync_expected— Don’t pass an async closure where a void-returning function is expected.