Skip to content

[2.0] Catch PDOException when MySQL server has gone away during SET SESSION wait_timeout reset#200

Merged
taylorotwell merged 1 commit intolaravel:2.0from
rizalpahlevii:fix/mysql-gone-away-octane-set-session
Mar 9, 2026
Merged

[2.0] Catch PDOException when MySQL server has gone away during SET SESSION wait_timeout reset#200
taylorotwell merged 1 commit intolaravel:2.0from
rizalpahlevii:fix/mysql-gone-away-octane-set-session

Conversation

@rizalpahlevii
Copy link
Contributor

Problem

When using explicit read/write connections (e.g. User::on('mysql::read'))
on Aurora or any MySQL server that aggressively drops idle connections,
the SET SESSION wait_timeout call in manageDatabaseSessions() fails
with:

PDOException: SQLSTATE[HY000]: General error: 2006 MySQL server has gone away

The user request itself completes successfully and receives the correct response.
However, the unhandled exception thrown in invokeRequestHandledCallbacks propagates
up to handleWorkerError which destabilizes the long-running Octane worker process,
potentially causing subsequent requests on the same worker to fail.

This happens because:

  1. manageDatabaseSessions runs POST-response via onRequestHandled
  2. Aurora drops the connection between request completion and callback execution
  3. getRawPdo()->exec() bypasses Laravel's reconnect logic entirely
  4. There is no try/catch protecting the SET SESSION call

Inconsistency

The disconnect() call above already has a try/catch with the comment
"Likely already disconnected..." — but SET SESSION has no such protection
despite the same failure mode.

Fix

Wrap SET SESSION execution in a try/catch, consistent with the existing
disconnect() handling above it.

Tests

Added 4 tests covering:

  • Bug exists without fix
  • Fix handles stale/gone away connections
  • Healthy connections still receive wait_timeout reset
  • Mixed live + stale connections (Aurora writer + reader scenario)

Production Stack Trace

Captured from Sentry on production (AWS Aurora, writer + reader,
triggered by explicit mysql::read connection usage):

PDO::exec
  in HigherOrderCollectionProxy.php:66
  statement: "SET SESSION wait_timeout=10"

Laravel\Vapor\Runtime\Octane\Octane::{closure}
  in vendor/laravel/vapor-core/src/Runtime/Octane/Octane.php:126  ← crash here
  })->map->getRawPdo()->filter(function ($pdo) {
      return $pdo instanceof PDO;
  })->each->exec(sprintf(
      'SET SESSION wait_timeout=%s', $databaseSessionTtl
  ));

Laravel\Octane\Worker::invokeRequestHandledCallbacks
  in vendor/laravel/octane/src/Worker.php:209

Laravel\Octane\Worker::handle
  in vendor/laravel/octane/src/Worker.php:102

The exception is thrown inside invokeRequestHandledCallbacks which executes
after $responded = true in Worker::handle — meaning the HTTP response has already
been flushed to the client. However, the unhandled exception propagates up to
handleWorkerError which can destabilize the long-running Octane worker process,
potentially causing subsequent requests on the same worker to fail.

@rizalpahlevii rizalpahlevii force-pushed the fix/mysql-gone-away-octane-set-session branch from dd2527a to 199e839 Compare March 7, 2026 13:28
@taylorotwell taylorotwell merged commit e25e8ed into laravel:2.0 Mar 9, 2026
2 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants