Skip to content

avoid_throw_in_catch_block

v0.4.0 Warning Fix Control Flow

Warns when a throw expression is used inside a catch block. Throwing a new exception (or re-throwing the caught one with throw e) discards the original stack trace, making debugging significantly harder. Use rethrow or Error.throwWithStackTrace() instead.

When you use throw inside a catch block, the original stack trace is lost. This means error reports and logs will point to the catch block instead of the actual source of the error. Using rethrow preserves the full stack trace, and Error.throwWithStackTrace() lets you throw a different exception while keeping the original stack trace attached.

See also: Exceptions

void bad() {
// throw loses original stack trace
try {
networkDataProvider();
} on Object {
throw RepositoryException();
}
// throw with caught exception still loses stack trace
try {
networkDataProvider();
} catch (e) {
throw e;
}
// throw with logic before it
try {
networkDataProvider();
} catch (e) {
print(e);
throw RepositoryException('failed');
}
}
void good() {
// Use Error.throwWithStackTrace to preserve the stack trace
try {
networkDataProvider();
} catch (_, stack) {
Error.throwWithStackTrace(RepositoryException(), stack);
}
// Use rethrow to re-throw the original exception
try {
networkDataProvider();
} catch (e) {
print(e);
rethrow;
}
// Throw inside a closure is fine — it's not in the catch scope
try {
networkDataProvider();
} catch (e) {
final callback = () {
throw RepositoryException();
};
callback();
}
}

To disable this rule:

plugins:
many_lints:
diagnostics:
avoid_throw_in_catch_block: false