Throwable Not Thrown
ID |
kotlin.throwable_not_thrown |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Kotlin |
Tags |
dead-code, exception, throw |
Description
Reports exception constructions whose result is never used. Constructing a Throwable subclass
as a bare expression-statement is meaningless — the exception is built, immediately garbage-
collected and never propagated. The most common cause is a missing throw keyword.
Rationale
// Bad — exception built and dropped, almost certainly a missing `throw`
fun guard(x: Int) {
if (x < 0) {
IllegalArgumentException("x must be non-negative") // FLAW
}
}
// OK — `throw` keyword present
fun guard(x: Int) {
if (x < 0) {
throw IllegalArgumentException("x must be non-negative")
}
}
// OK — constructed exception is consumed
val ex = IllegalStateException("boom")
logger.error("failed", IllegalStateException("boom"))
The rule is conservative and only fires when the constructor call is a bare expression-statement
with no consumer in the AST. Calls inside assignments, return statements, throw expressions,
function arguments, or chained .message accesses are not flagged.
Remediation
-
Add the missing
throwkeyword if the intent was to propagate the exception. -
Assign the constructed exception to a variable if it really is meant to be a value.
-
Pass the exception as a constructor or function argument to consume it (e.g. as a cause).