Rules / Suspicious / use-rethrow-when-possible

use-rethrow-when-possible

lint/suspicious/use-rethrow-when-possible
recommended
Same as use_rethrow_when_possible · Dart lints

Flags throw e inside a catch (e) where e is exactly the caught exception.

Re-throwing the caught object with throw e starts a fresh stack trace from the catch site, discarding the original point of failure and making the error far harder to trace. Use rethrow, which propagates the same exception with its trace intact. Reporting is conservative: a throw is flagged only where rethrow would be valid and refer to the same binding, so throws inside a nested closure or a nested try/catch are skipped.

Invalid

example.dartdart
// Bad: re-throwing the caught exception with `throw e` instead of `rethrow`.
bool cond = true;
void x() {}
void log(Object o) {}

void a() {
  try {
    x();
  } catch (e) {
    throw e;
  }
}

void b() {
  try {
    x();
  } catch (e) {
    log(e);
    throw e;
  }
}

void c() {
  try {
    x();
  } catch (e) {
    if (cond) {
      throw e;
    }
  }
}

void d() {
  try {
    x();
  } on Exception catch (e) {
    throw e;
  }
}

void e2() {
  try {
    x();
  } catch (err, st) {
    log(st);
    throw err;
  }
}
Use `rethrow` to re-throw the caught exception and preserve its stack trace.
9 } catch (e) {
10 throw e;
Use `rethrow` to re-throw the caught exception and preserve its stack trace.
18 log(e);
19 throw e;
Use `rethrow` to re-throw the caught exception and preserve its stack trace.
27 if (cond) {
28 throw e;
Use `rethrow` to re-throw the caught exception and preserve its stack trace.
36 } on Exception catch (e) {
37 throw e;
Use `rethrow` to re-throw the caught exception and preserve its stack trace.
45 log(st);
46 throw err;

Valid

example.dartdart
// Good: `rethrow`, or a throw that is not equivalent to rethrowing the caught exception.
void x() {}
void y() {}
void log(Object o) {}

void a() {
  try {
    x();
  } catch (e) {
    rethrow; // already uses rethrow
  }
}

void b() {
  try {
    x();
  } catch (e) {
    throw StateError('nope'); // throws a different object
  }
}

void c() {
  try {
    x();
  } catch (e) {
    throw Exception(e); // wraps e rather than rethrowing it
  }
}

void d() {
  try {
    x();
  } catch (e) {
    void handler() {
      throw e; // inside a nested function: rethrow would be illegal here
    }

    handler();
  }
}

void e2() {
  try {
    x();
  } catch (e) {
    try {
      y();
    } catch (e2) {
      throw e; // refers to the outer exception; rethrow is not valid here
    }
  }
}

void f() {
  try {
    x();
  } catch (e) {
    final cb = () {
      throw e; // inside a closure expression
    };
    cb();
  }
}

How to configure

Set the severity of use-rethrow-when-possible in your falcon.json:

falcon.jsonjson
{
  "linter": {
    "rules": {
      "suspicious": {
        "use-rethrow-when-possible": "error"
      }
    }
  }
}