use-rethrow-when-possible
Same as use_rethrow_when_possible in Dart lints
- Group
- Suspicious
- Path
lint/suspicious/use-rethrow-when-possible- Default
- On (recommended)
- Origin
- Dart lints
- Rule
- 501 of 512
Flags throw e inside a catch (e) by matching the exception parameter's name.
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. Matching is syntactic: the thrown identifier must have the
exception parameter's spelling; binding identity is not resolved. Throws
inside a nested closure or a nested try/catch are skipped.
Invalid
// 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;
}
}
void nestedCatchInsideFunctionBoundaries() {
try {
x();
} catch (outer) {
final callback = () {
try {
x();
} catch (inner) {
throw inner;
}
};
void local() {
try {
x();
} catch (inner) {
throw inner;
}
}
callback();
local();
throw outer;
}
} } catch (e) { throw e; log(e); throw e; if (cond) { throw e; } on Exception catch (e) { throw e; log(st); throw err; } catch (inner) { throw inner; } catch (inner) { throw inner; local(); throw outer;Valid
// 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();
}
}
void nestedTryDoesNotRethrowOuterBinding() {
try {
x();
} catch (outer) {
try {
throw outer;
} catch (inner) {
throw outer;
} finally {
throw outer;
}
}
}Configure use-rethrow-when-possible
Set its severity in falcon.json. See the configuration guide.
{
"linter": {
"rules": {
"suspicious": {
"use-rethrow-when-possible": "error"
}
}
}
}Or silence one occurrence with a suppression comment; the reason is required.
// falcon-ignore lint/suspicious/use-rethrow-when-possible: <reason>More suspicious rules
- avoid-accessing-other-classes-private-members
Enforces class-level encapsulation even inside one Dart library.
- avoid-assignments-as-conditions
Flags assignments evaluated inside control-flow conditions.
- avoid-banned-annotations
Ban configured dotted annotation names, without the leading
@. - avoid-banned-exports
Ban decoded export URIs, including all conditional alternatives.
- avoid-banned-names
Ban declaration names, exempting references, initializing/super formals, and
@override-annotated members and their parameters. - avoid-banned-types
Ban resolved explicit type annotations, including nested generic arguments.
- avoid-barrel-files
Discourage files containing only re-exports, without declarations or parts.
- avoid-bitwise-operators-with-booleans
Flags
&and|applied to two non-nullable boolean operands.