Use finally for cleanup, not for choosing a function result. A return inside finally takes precedence over an earlier return and can prevent an exception already in flight from reaching the caller.
Last updated: October 26, 2026.
<?php
function readFirstLine(string $path): string
{
$handle = fopen($path, 'rb');
if ($handle === false) {
throw new RuntimeException('File could not be opened.');
}
try {
$line = fgets($handle);
if ($line === false) {
throw new RuntimeException('File does not contain a line.');
}
return rtrim($line, "
");
} finally {
fclose($handle); // Cleanup only; no return here.
}
}The pending return value or exception continues after fclose() runs. Keeping cleanup separate makes the function outcome visible in the try or catch block where it belongs.
Why return in finally is dangerous
The PHP finally documentation states that the block executes before normal flow resumes. If try or catch returns, PHP evaluates that value, executes finally, and then returns it. But if finally also returns, its value replaces the earlier one.
The same control-flow rule can hide an exception thrown in try or catch. That changes a failed operation into an apparently successful return and removes the stack trace from normal error handling. Static analysis rules that prohibit control-flow statements in cleanup blocks are worth enabling.
Let cleanup failures remain visible
The dedicated PHP finally reference confirms that cleanup runs even when a Throwable is rethrown. Close files, release locks, restore temporary state, or end tracing in the block, but avoid return, break, and unrelated business decisions.
If cleanup itself can throw, decide deliberately which failure should reach the caller. PHP preserves the earlier exception as the previous exception when a new exception is thrown from finally, but logging and resource APIs may require local handling. Do not silently catch a cleanup exception merely to keep an earlier return value. Continue with cleaning up temporary files, handling PHP runtime failures, and writing clear PHP functions.