avoid-throw-in-catch-block
Same as avoid-throw-in-catch-block in Dart Code Metrics
- Group
- Suspicious
- Path
lint/suspicious/avoid-throw-in-catch-block- Default
- Off, opt in
- Origin
- Dart Code Metrics
- Rule
- 145 of 512
Flags throw statements inside a catch block.
Throwing a fresh exception from a catch replaces the error in flight along
with its original stack trace, so the root cause is lost and the failure
becomes much harder to diagnose. Prefer rethrow to propagate the caught
exception unchanged, or wrap it in an error that keeps the original as a
cause. Every throw statement is reported, including throws of existing
values; rethrow is always exempt. Delayed local functions and closures are
separate execution scopes and are not part of the surrounding catch.
Invalid
// Test cases for avoid-throw-in-catch-block rule
// All violations are annotated inline
void readFile() {
try {
final file = File('missing.txt').readAsStringSync();
} catch (e) {
throw Exception('Failed to read file: $e');
}
}
Future<String> fetchData() {
try {
return http.get(url);
} catch (e, st) {
throw Exception('Network error: $e');
}
}
class Database {
void connect() {
try {
_establishConnection();
} catch (error) {
throw DatabaseException('Connection failed');
}
}
void update(String query) {
try {
_executeQuery(query);
} on TimeoutException catch (e) {
throw TimeoutException('Update timeout: ${e.message}');
} catch (e) {
throw RuntimeException(e.toString());
}
}
}
void parseJson(String json) {
try {
jsonDecode(json);
} catch (e) {
throw FormatException('Invalid JSON');
}
}
void nestedTryCatch() {
try {
try {
doSomething();
} catch (e) {
throw CustomException('Inner error');
}
} catch (e) {
print('Outer handler: $e');
}
}
Future<void> multipleThrows() {
try {
return riskyOperation();
} on NotFoundException catch (e) {
throw ApiException('Not found: ${e.message}');
} on TimeoutException catch (e) {
throw ApiException('Timeout: ${e.message}');
}
} } catch (e) { throw Exception('Failed to read file: $e'); } catch (e, st) { throw Exception('Network error: $e'); } catch (error) { throw DatabaseException('Connection failed'); } on TimeoutException catch (e) { throw TimeoutException('Update timeout: ${e.message}'); } catch (e) { throw RuntimeException(e.toString()); } catch (e) { throw FormatException('Invalid JSON'); } catch (e) { throw CustomException('Inner error'); } on NotFoundException catch (e) { throw ApiException('Not found: ${e.message}'); } on TimeoutException catch (e) { throw ApiException('Timeout: ${e.message}');Valid
// Good cases for avoid-throw-in-catch-block rule
// No violations expected
void readFile() {
try {
final file = File('missing.txt').readAsStringSync();
} catch (e) {
rethrow;
}
}
Future<String> fetchData() {
try {
return http.get(url);
} catch (e, st) {
rethrow;
}
}
class Database {
void connect() {
try {
_establishConnection();
} catch (error) {
rethrow;
}
}
void update(String query) {
try {
_executeQuery(query);
} on TimeoutException catch (e) {
rethrow;
} catch (e) {
rethrow;
}
}
}
void parseJson(String json) {
try {
jsonDecode(json);
} catch (e) {
print('Failed to parse JSON: $e');
}
}
void handleGracefully() {
try {
riskyOperation();
} catch (e) {
logger.error('Operation failed', error: e);
}
}
void logAndReturn() {
try {
doSomething();
} catch (e) {
_handleError(e);
}
}
Future<String> withFallback() {
try {
return fetchData();
} catch (e) {
return Future.value('default');
}
}
void withCallback() {
try {
process();
} catch (e) {
onError?.call(e);
}
}
class ErrorHandler {
void handle(Error error) {
try {
_sendToServer(error);
} catch (e) {
logger.warn('Could not send error to server: $e');
}
}
}
void cleanupOnError() {
try {
resource.allocate();
resource.use();
} catch (e) {
resource.dispose();
}
}Configure avoid-throw-in-catch-block
Set its severity in falcon.json. See the configuration guide.
{
"linter": {
"rules": {
"suspicious": {
"avoid-throw-in-catch-block": "error"
}
}
}
}Or silence one occurrence with a suppression comment; the reason is required.
// falcon-ignore lint/suspicious/avoid-throw-in-catch-block: <reason>More suspicious rules
- avoid-top-level-members-in-teststest
Requires public declarations in test files, except main, to be private.
- avoid-types-as-parameter-names
avoid_types_as_parameter_namesrecommendedFlags implicit formal parameters, catch variables, and type parameters that shadow a type in their enclosing scope.
- avoid-unrelated-type-assertions
avoid-unrelated-type-assertionsrecommendedFlags an
ischeck proven impossible by canonical resolved types. - banned-usage
Ban resolved API references, not identifiers that merely share their spelling.
- cascade-after-null-coalescing
Flags a cascade after an unparenthesized null-coalescing expression.
- control-flow-in-finally
control_flow_in_finallyrecommendedFlags
return,break, orcontinuethat escapes afinallyblock. - empty-catches
empty_catchesrecommendedFlags empty
catchblocks. - empty-statements
empty_statementsrecommendedFlags stray empty statements (a lone
;).