symfony/http-foundation · error · DomainException

SQLite does not support advisory locks.

Error message

SQLite does not support advisory locks.

What it means

This DomainException is thrown by PdoSessionHandler::doAdvisoryLock() when the handler is configured with lock_mode LOCK_ADVISORY (lock_mode option = 3) and the underlying PDO driver is 'sqlite'. SQLite has no advisory-lock functions (no GET_LOCK / pg_advisory_lock equivalent), so the handler refuses to operate instead of providing weaker guarantees. The error surfaces when a read (doRead) triggers the advisory lock acquisition.

Solutions

  1. Remove the 'lock_mode' option (or set it to PdoSessionHandler::LOCK_NONE) when using a sqlite connection — SQLite serializes writes via its own file lock, so advisory locking is unnecessary.
  2. Switch the session store to the production database (mysql/pgsql DSN) if advisory locking semantics are genuinely needed.
  3. Use PdoSessionHandler::LOCK_TRANSACTIONAL instead, which is supported for sqlite (locking is done via the transaction: 'we already locked when starting transaction').
  4. Differentiate config per environment: define lock_mode only for drivers that support advisory locks (mysql, pgsql).

Example fix

// before
$handler = new PdoSessionHandler($pdo, ['lock_mode' => PdoSessionHandler::LOCK_ADVISORY]);

// after (sqlite)
$handler = new PdoSessionHandler($pdo, ['lock_mode' => PdoSessionHandler::LOCK_TRANSACTIONAL]);
Defensive patterns

Strategy: validation

Validate before calling

$driver = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
if ('sqlite' === $driver && ($options['lock_mode'] ?? null) === PdoSessionHandler::LOCK_ADVISORY) {
    unset($options['lock_mode']); // or use LOCK_TRANSACTIONAL
}

Try / catch

try {
    $session->start();
} catch (\DomainException $e) {
    if (str_contains($e->getMessage(), 'does not support advisory locks')) {
        // rebuild handler with LOCK_TRANSACTIONAL or LOCK_NONE
    } else {
        throw $e;
    }
}

Prevention

When it happens

Trigger: Constructing PdoSessionHandler with ['lock_mode' => PdoSessionHandler::LOCK_ADVISORY] (or db_connection options setting advisory locking) on a PDO connection whose driver is sqlite, then opening a session (session_start() -> read() -> doRead() -> doAdvisoryLock()).

Common situations: Local dev or test environments using sqlite:// DSN while the session config was written for MySQL/PostgreSQL production (lock_mode carried over from prod config); copying a framework bundle config with LOCK_ADVISORY into a sqlite-based project; fixture/test databases using PDO sqlite.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of symfony/http-foundation@5aea19cd67 (2026-09-13). Data as JSON: /api/errors/da97c66e39c3a4ac. Report an issue: GitHub.

Appendix: source

Thrown at Session/Storage/Handler/PdoSessionHandler.php:805

                    $stmt->execute();

                    $releaseStmt = $this->pdo->prepare('SELECT pg_advisory_unlock(:key1, :key2)');
                    $releaseStmt->bindValue(':key1', $sessionInt1, \PDO::PARAM_INT);
                    $releaseStmt->bindValue(':key2', $sessionInt2, \PDO::PARAM_INT);
                } else {
                    $sessionBigInt = $this->convertStringToInt($sessionId);

                    $stmt = $this->pdo->prepare('SELECT pg_advisory_lock(:key)');
                    $stmt->bindValue(':key', $sessionBigInt, \PDO::PARAM_INT);
                    $stmt->execute();

                    $releaseStmt = $this->pdo->prepare('SELECT pg_advisory_unlock(:key)');
                    $releaseStmt->bindValue(':key', $sessionBigInt, \PDO::PARAM_INT);
                }

                return $releaseStmt;
            case 'sqlite':
                throw new \DomainException('SQLite does not support advisory locks.');
            default:
                throw new \DomainException(\sprintf('Advisory locks are currently not implemented for PDO driver "%s".', $this->driver));
        }
    }

    /**
     * Encodes the first 4 (when PHP_INT_SIZE == 4) or 8 characters of the string as an integer.
     *
     * Keep in mind, PHP integers are signed.
     */
    private function convertStringToInt(string $string): int
    {
        if (4 === \PHP_INT_SIZE) {
            return (\ord($string[3]) << 24) + (\ord($string[2]) << 16) + (\ord($string[1]) << 8) + \ord($string[0]);
        }

        $int1 = (\ord($string[7]) << 24) + (\ord($string[6]) << 16) + (\ord($string[5]) << 8) + \ord($string[4]);
        $int2 = (\ord($string[3]) << 24) + (\ord($string[2]) << 16) + (\ord($string[1]) << 8) + \ord($string[0]);

View on GitHub (pinned to 5aea19cd67)