Skip to content

proposal: lint to catch unawaited futures in try blocks #59155

Closed
@eseidel

Description

@eseidel

The gotcha occurs when you return Future<T> from Future<T> foo async {} instead of T and that return is inside a try block.

https://twitter.com/_eseidel/status/1660092263190650881

https://dartpad.dev/?id=f4c93eb9f9e24d43079cbc859a867894

class ApiException implements Exception {
  ApiException();
}

Future<void> inner() async {
  throw ApiException();
}

Future<void> _middle() async {
  try {
    return inner();
  } on ApiException catch (e) {
    print('inner: $e');
  }
}

Future<void> outer() async {
  try {
    await _middle();
  } on ApiException catch (e) {
    print('outer: $e');
  }
}

void main() async {
  await outer();
}

Would love a lint that would have caught that (and saved me -- and clearly others according to responses on that twitter thread) a while of searching for the issue.

Discussion checklist

  • List any existing rules this proposal modifies, complements, overlaps or conflicts with.

unawaited_futures could have some overlap, although it doesn't trigger here.

unnecessary_await_in_return seems in direct conflict.

  • List any relevant issues (reported here, the [SDK Tracker], or elsewhere).

  • If there's any prior art (e.g., in other linters), please add references here.
    https://dcm.dev/docs/teams/rules/common/prefer-return-await/

  • If this proposal corresponds to [Effective Dart] or [Flutter Style Guide] advice, please call it out. (If there isn't any corresponding advice, should there be?)

  • If this proposal is motivated by real-world examples, please provide as many details as you can. Demonstrating potential impact is especially valuable.

Arguably the real bug is that Future<T> foo async {} allows returning Future<T> directly at all, since it nominally expects you to return a T. But presumably that's an intentional language decision.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions