Skip to content

PHP 8.0+ bug: catch variable shadows closure parameter causing "Undefined variable $exception" in submitMessages rejection handler #7

Description

@aasimsajjad22

Bug Description

In PHP 8.0+, catch clause variables are unset after the catch block exits. In the submitMessages rejection callback, the catch variable is named $exception — the same name as the closure parameter. When the catch block runs, it shadows and then unsets the closure parameter. The throw $exception after the catch block then fails with Error: Undefined variable $exception.

Affected Code

src/Flowmailer.php — rejection callback inside submitMessages:

function ($exception) use ($guzzlePromise) {   // ← closure parameter
    try {
        if ($exception instanceof ClientErrorException) {
            $responseError = $this->handleResponseError($exception->getResponse());
            $guzzlePromise->reject($responseError);
            return $exception->getResponse();
        } else {
            $guzzlePromise->reject($exception);
        }
    } catch (\Exception $exception) {          // ← shadows + overwrites closure parameter
        $guzzlePromise->reject($exception);
    }
    // PHP 8.0+: $exception is now UNSET (catch variable scope ends here)

    throw $exception;                          // ← Error: Undefined variable $exception
}

Root Cause

PHP 8.0 changed the scoping of catch clause variables — they are unset when the catch block exits. Because the catch variable has the same name ($exception) as the closure parameter, the parameter is overwritten and then destroyed when the catch block ends. PHP 8.0 migration reference.

Fix

Rename the catch variable so it does not shadow the closure parameter:

-        } catch (\Exception $exception) {
-            $guzzlePromise->reject($exception);
+        } catch (\Exception $caughtError) {
+            $guzzlePromise->reject($caughtError);
         }

Impact

  • Email deliveries are silently marked as failed with a misleading error message: "Flowmailer email sending failed: Undefined variable $exception" instead of the real underlying error
  • The MessageSendingFailed event fires and the recipient never receives their email
  • Occurs when the promise rejection path is triggered (e.g. network errors, auth failures)

Environment

  • PHP: 8.4.x (confirmed in production), but affects any PHP 8.0+
  • SDK version: 2.3.1 (latest)
  • Triggered via: submitMessages() → async promise rejection callback

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions