Rules / Suspicious / use-rethrow-when-possible
use-rethrow-when-possible
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.
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"
}
}
}
}