Throwing Exception From Finally
ID |
kotlin.throwing_exception_from_finally |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Kotlin |
Tags |
control-flow, exception, finally |
Description
Reports throw expressions inside finally blocks. A throw executed in finally silently
masks any exception that may be propagating from the corresponding try body. The caller sees
only the new exception, with no indication that the original failure occurred.
Rationale
// Bad — exception from parse() is lost
fun load(): Int {
try {
return parse()
} finally {
throw IllegalStateException("cleanup failed") // FLAW
}
}
// OK — finally only performs cleanup
fun load(): Int {
try {
return parse()
} finally {
cleanup()
}
}
Masking exceptions in finally hides root causes, complicates diagnosis and turns reproducible
failures into intermittent ones.
Remediation
-
Keep
finallyblocks limited to cleanup logic that does not throw. -
If a cleanup failure must be signalled, log it and let the original exception propagate, or attach the cleanup failure as a suppressed exception via
addSuppressed(…). -
Throws inside lambdas / local functions nested in the finally are not reported because they stay confined to the nested scope.