symfony/http-foundation · error · DomainException

Advisory locks are currently not implemented for PDO driver

Error message

Advisory locks are currently not implemented for PDO driver "%s".

What it means

This DomainException is the default branch of PdoSessionHandler::doAdvisoryLock(): advisory (application-level) locking is only implemented for the 'mysql' (GET_LOCK) and 'pgsql' (pg_advisory_lock) drivers. Any other PDO driver — e.g. oci, sqlsrv, dblib — hits this branch when doRead() requests LOCK_ADVISORY mode. The class docblock also notes oci (DBMS_LOCK.REQUEST) and sqlsrv (sp_getapplock) implementations are still a TODO.

Solutions

  1. Use PdoSessionHandler::LOCK_TRANSACTIONAL instead of LOCK_ADVISORY — transactional locking is implemented for mysql, pgsql, oci and sqlsrv (via SELECT ... FOR UPDATE / WITH (UPDLOCK, ROWLOCK)).
  2. Remove the 'lock_mode' option entirely to use the default transactional locking.
  3. If advisory locking on sqlsrv/oci is required, implement sp_getapplock / DBMS_LOCK.REQUEST yourself in a subclass overriding the locking strategy (upstream has it as a @todo).
  4. Only set LOCK_ADVISORY when the DSN driver is mysql or pgsql; guard the option per environment.

Example fix

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

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

Strategy: validation

Validate before calling

$driver = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
if (!in_array($driver, ['mysql', 'pgsql'], true) && ($options['lock_mode'] ?? null) === PdoSessionHandler::LOCK_ADVISORY) {
    $options['lock_mode'] = PdoSessionHandler::LOCK_TRANSACTIONAL;
}

Try / catch

try {
    $session->start();
} catch (\DomainException $e) {
    if (str_contains($e->getMessage(), 'Advisory locks are currently not implemented')) {
        // reconfigure handler with LOCK_TRANSACTIONAL for this driver
    } else {
        throw $e;
    }
}

Prevention

When it happens

Trigger: PdoSessionHandler constructed with ['lock_mode' => PdoSessionHandler::LOCK_ADVISORY] on a PDO connection whose ->getAttribute(PDO::ATTR_DRIVER_NAME) is not 'mysql' or 'pgsql' (e.g. oci:, sqlsrv:, dblib:), then any session read triggers doAdvisoryLock() and throws.

Common situations: Running Symfony sessions on Oracle or SQL Server with a lock_mode copied from a MySQL/Postgres configuration; custom PDO wrappers reporting unusual driver names; switching production databases without revisiting session handler options.

Related errors


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

Appendix: source

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

                    $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]);

        return $int2 + ($int1 << 32);

View on GitHub (pinned to 5aea19cd67)