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
- 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)).
- Remove the 'lock_mode' option entirely to use the default transactional locking.
- 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).
- 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
- Only use LOCK_ADVISORY on mysql/pgsql connections
- Prefer the default LOCK_TRANSACTIONAL, which has per-driver SQL for mysql, pgsql, oci, sqlsrv and sqlite
- Check PDO::ATTR_DRIVER_NAME (not the DSN string) to decide lock mode
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
- Transactional locks are currently not implemented for PDO…
- " " requires PDO error mode attribute be set to throw…
- SQLite does not support advisory locks.
- Creating the session table is currently not implemented for…
- You must provide the "database" and "collection" option for…
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)