prefer_return_await
v0.4.0 Warning Fix Control Flow
Warns when a Future is returned without await inside a try-catch block in an async function. Without await, any exception thrown by the Future will not be caught by the surrounding catch block, silently bypassing your error handling.
Why use this rule
Section titled “Why use this rule”When you write return asyncOp() inside a try-catch, the Future is returned to the caller without being awaited. If asyncOp() throws, the exception propagates to the caller instead of being caught by the local catch block. Adding await ensures the Future completes within the try-catch scope, so exceptions are properly caught and handled.
See also: Asynchronous programming | Dart lint: unnecessary_await_in_return
Future<String> fetchToken() async => 'token';
Future<String> token() async { try { // fetchToken() completes after this function has already returned, so // its exception never reaches the catch below. return fetchToken(); } catch (e) { return 'anonymous'; }}Future<String> fetchToken() async => 'token';
Future<String> token() async { try { return await fetchToken(); } catch (e) { return 'anonymous'; }}A return inside a catch clause escapes an outer try just as easily, so it needs the await too:
Future<String> fetchToken() async => 'token';Future<String> retryToken() async => 'token';
Future<String> token() async { try { return await fetchToken(); } catch (e) { // Don't — this Future escapes any enclosing try as well. return retryToken(); }}Known limitations
Section titled “Known limitations”Three shapes are deliberately not reported:
Outside any try-catch. There is no local scope to keep the Future inside, and the caller owns the error:
Future<String> fetchToken() async => 'token';
Future<String> token() async => fetchToken();A non-async function. It has no try-catch scope for the Future to complete in, so returning it unawaited is the only option:
Future<String> fetchToken() async => 'token';
Future<String> token() { try { return fetchToken(); } catch (e) { return Future.value('anonymous'); }}A finally block. A return there is already outside the guarded region.
Recent Dart SDKs ship a built-in unawaited_return_in_try_block warning that
covers the try body case, so you may see two diagnostics on the same line
there. The catch clause is this rule’s alone.
Configuration
Section titled “Configuration”This rule is in the core preset, so it is on with preset: core,
preset: recommended or preset: opinionated.
To turn it off:
rules: prefer_return_await: falseTo keep the rule on but skip certain paths, use per-rule exclude.
Related rules
Section titled “Related rules”avoid_unnecessary_return— Remove a barereturn;that ends a void function.prefer_early_return— Replace a body-wrapping if with an early-return guard.avoid_cascade_after_if_null— Detect cascades after if-null operators without parentheses.avoid_collapsible_if— Merge nested if statements with &&.