PHP 8.6 will emit a deprecation notice when a return statement appears inside a finally block. Osama Aldemeery proposed the change in the PHP 8.6 deprecations RFC and contributed the implementation to php-src.

The problem is easy to miss. A return inside finally can replace an earlier return value or stop an exception from reaching the caller.

How an Exception Can Disappear

The RFC gives this example:

function getConfig(): array {
    try {
        return loadConfig(); // Throws if the file is missing
    } finally {
        return []; // The exception is discarded
    }
}

If loadConfig() throws an exception, the caller never receives it. The finally block returns an empty array instead, making the function look as if it completed normally.

The same rule applies to return values. If both try and finally return a value, the value from finally wins.

PHP does not change that behavior in 8.6. It adds a warning so developers can find the pattern before it becomes an error in a future version.

What Triggers the Deprecation

PHP checks the code during compilation and emits this E_DEPRECATED message:

Deprecated: Returning from a finally block is deprecated

Both return; and return $value; trigger the notice when written inside finally.

The check follows where the statement is written:

  • A return inside try or catch is not deprecated.
  • A return inside a closure created within finally belongs to the closure, so it is not affected by the outer block.
  • A return inside a nested try that sits within finally is deprecated.
  • A closure with its own finally block is checked separately.

The Vote and Expected Impact

The proposal passed with 39 votes in favor, three against, and four abstentions. Voting closed on August 10, 2026.

A scan of about 5,000 widely installed Composer packages found 12 examples across nine packages. The RFC says nine were harmless or intentional. In the other three, the code could discard a real exception.

Most projects are unlikely to have this pattern, but static analysis and test runs on PHP 8.6 should make affected code visible.

How to Update the Code

Start by searching for return statements inside finally blocks. The right fix depends on the intent.

If the return was accidental, move it outside finally. A finally block should usually handle cleanup, such as closing a file or releasing a lock.

If the code meant to handle an exception, catch that exception directly:

function getConfig(): array {
    try {
        return loadConfig();
    } catch (ConfigException) {
        return [];
    }
}

This version returns the same fallback value, but it makes the decision clear and does not hide unrelated exceptions.

The behavior remains available in PHP 8.6, with a deprecation notice. Review the implementation commit for the compiler change and its edge-case tests. Our PHP 8.6 deprecation coverage explains the other proposals from the same RFC.