return, break or continue inside a finally block
ID |
dart.correctness.control_flow_in_finally |
Severity |
low |
Remediation Complexity |
medium |
Remediation Risk |
medium |
Remediation Effort |
medium |
Resource |
Control Flow |
Language |
Dart |
Description
Reports return, break and continue statements written directly in a finally block, rather than inside a loop, switch or closure that the finally block itself contains.
Rationale
A finally block runs while an exception is still propagating. Transferring control out of it abandons that propagation: the exception is discarded, the caller sees a normal completion, and the value the try block was about to return is replaced. The failure then disappears without a trace, which is the hardest class of bug to diagnose because the code looks like it succeeded. A return in the finally block also silently overrides a return in the try block, so the two read as if both took effect when only one does.
The following code illustrates the pattern detected by this rule:
class Uploader {
bool sendAll(List<String> items) {
for (final item in items) {
// FLAGGED: return, break or continue inside a finally block
try {
send(item);
} finally {
close();
continue;
}
}
return true;
}
bool transmit(String item) => true;
void close() {}
void log(String m) {}
bool closed = false;
}
Remediation
Keep the finally block to cleanup that cannot fail — closing handles, releasing locks, restoring state — and let control flow stay in the try or catch block. If a value really has to be replaced or a loop cut short, do it after the try statement, or move the decision into a catch clause where the exception is handled explicitly.