Return From Finally

ID

kotlin.return_from_finally

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Kotlin

Tags

CWE:584, exception, finally

Description

Reports return statements inside finally blocks that silently discard exceptions propagating from the try body.

When a finally block executes a return, the JVM discards any exception that was actively unwinding the stack. The caller receives the return value and has no indication that an error occurred, making the failure completely invisible.

Rationale

// Bad — exception from readConfig() is silently lost
fun loadConfig(): Config {
    try {
        return readConfig()
    } finally {
        return Config.DEFAULT  // FLAW — IOException from readConfig() discarded
    }
}

// Good — finally only cleans up; exceptions propagate normally
fun loadConfig(): Config {
    val stream = openStream()
    try {
        return readConfig(stream)
    } finally {
        stream.close()
    }
}

Remediation

  • Remove the return statement from the finally block.

  • Move cleanup logic into finally and return values only from the try or catch blocks.

  • If a default value is needed on error, use a catch block to capture the exception, log it, and return the fallback explicitly.