Skip to content

Only catch UniqueConstraintViolationException in database session insert (fixes laravel/framework#57961)#7

Open
JoshSalway wants to merge 2 commits into12.xfrom
fix/session-database-suppress-errors-12x
Open

Only catch UniqueConstraintViolationException in database session insert (fixes laravel/framework#57961)#7
JoshSalway wants to merge 2 commits into12.xfrom
fix/session-database-suppress-errors-12x

Conversation

@JoshSalway
Copy link
Owner

@JoshSalway JoshSalway commented Mar 18, 2026

Summary

Fixes laravel#57961 -- The database session handler catches all QueryException errors during insert, silently swallowing real database errors (missing tables, permission denied, connection failures) and falling through to an update that also fails, producing confusing error messages.

Root Cause

The bug exists because DatabaseSessionHandler::performInsert() catches the broad QueryException class when the insert fails, then falls through to performUpdate(). The intent was to handle the specific case where a session ID already exists (race condition between two requests), but QueryException covers every possible database error -- missing tables, invalid columns, connection timeouts, permission denied, etc. These unrelated errors are silently caught and masked by a subsequent update failure.

Why This Fix Works

This fix works because it narrows the catch clause to UniqueConstraintViolationException, which is the specific subclass of QueryException that represents a duplicate key violation. This is the only scenario where falling through to performUpdate() makes sense -- the session record already exists, so updating it is the correct recovery. All other database errors now propagate immediately with their original, meaningful error messages.

Alternatives Considered

We chose this approach over adding a SELECT-before-INSERT pattern because: (1) the race condition would still exist between the SELECT and INSERT; (2) the current insert-then-update pattern is a well-established "upsert" strategy that avoids extra queries; (3) UniqueConstraintViolationException was specifically introduced in Laravel to enable this exact pattern -- precise catch handling for constraint violations. Catching the narrower exception preserves the upsert optimization while fixing the error-swallowing bug.

Files Changed

  • src/Illuminate/Session/DatabaseSessionHandler.php -- Changed catch from QueryException to UniqueConstraintViolationException
  • tests/Integration/Session/DatabaseSessionHandlerTest.php -- New test verifying non-unique-constraint errors are rethrown

JoshSalway and others added 2 commits March 19, 2026 04:43
…ndler

Verifies that DatabaseSessionHandler::performInsert() re-throws
QueryException when the error is not a unique constraint violation.

Refs laravel#57961

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
DatabaseSessionHandler::performInsert() caught all QueryException
instances and silently fell back to an update. This suppressed real
database errors (missing columns, schema mismatches) making them
impossible to diagnose.

Narrow the catch to UniqueConstraintViolationException, which is the
only case where the insert-then-update fallback is appropriate (race
condition on duplicate session ID). All other query errors are now
properly propagated.

Fixes laravel#57961

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

1 participant