symfony/http-foundation · error · DomainException
Transactional locks are currently not implemented for PDO…
Error message
Transactional locks are currently not implemented for PDO driver "%s".
What it means
This DomainException comes from PdoSessionHandler::getSelectSql() when lock_mode is LOCK_TRANSACTIONAL and the PDO driver is neither mysql, pgsql, oci, sqlsrv, nor sqlite. getSelectSql() builds the row-locking SELECT (FOR UPDATE / WITH (UPDLOCK, ROWLOCK)) per driver; an unrecognized driver has no known row-lock syntax, so the handler throws instead of silently reading without a lock. It is reached from doRead() during session_start().
Solutions
- Use a supported driver/DSN: switch pdo_dblib to pdo_sqlsrv ('sqlsrv:') for SQL Server, or use mysql/pgsql/oci/sqlite.
- If row-level locking is genuinely unavailable, set 'lock_mode' => PdoSessionHandler::LOCK_NONE (accepting weaker concurrency guarantees).
- Log/inspect (new PDO(...))->getAttribute(PDO::ATTR_DRIVER_NAME) to confirm which driver name the handler sees and align the DSN accordingly.
- Subclass PdoSessionHandler and override getSelectSql()/doRead() to emit correct locking SQL for your driver.
Example fix
// before (FreeTDS driver not supported)
$pdo = new PDO('dblib:host=mssql;dbname=app', $user, $pass);
// after
$pdo = new PDO('sqlsrv:Server=mssql;Database=app', $user, $pass); Defensive patterns
Strategy: validation
Validate before calling
$driver = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
$supported = ['mysql', 'pgsql', 'oci', 'sqlsrv', 'sqlite'];
if (!in_array($driver, $supported, true)) {
$options['lock_mode'] = PdoSessionHandler::LOCK_NONE; // or switch driver
} Try / catch
try {
$session->start();
} catch (\DomainException $e) {
if (str_contains($e->getMessage(), 'Transactional locks are currently not implemented')) {
// fall back to a driver-appropriate handler (e.g. LOCK_NONE or native files)
} else {
throw $e;
}
} Prevention
- Verify the actual PDO driver name at bootstrap; 'dblib' is NOT 'sqlsrv'
- Use pdo_sqlsrv for SQL Server so the handler recognizes the driver
- Compare PDO::ATTR_DRIVER_NAME against mysql/pgsql/oci/sqlsrv/sqlite before enabling the handler
When it happens
Trigger: PdoSessionHandler on a PDO driver other than mysql/pgsql/oci/sqlsrv/sqlite (e.g. dblib for SQL Server, ibm, custom PDO subclass) with the default LOCK_TRANSACTIONAL lock mode (or lock_mode explicitly set to it), then opening a session.
Common situations: Connecting to SQL Server via pdo_dblib (FreeTDS) instead of pdo_sqlsrv, so ATTR_DRIVER_NAME reports 'dblib'; exotic PDO drivers; misconfigured DSNs that pick an unexpected driver; frameworks bundle config moved to a different database platform.
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
- Advisory locks are currently not implemented for PDO driver
- " " 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/8b496fca9f6d80e7.
Report an issue: GitHub.
Appendix: source
Thrown at Session/Storage/Handler/PdoSessionHandler.php:849
* @throws \DomainException When an unsupported PDO driver is used
*/
private function getSelectSql(): string
{
if (self::LOCK_TRANSACTIONAL === $this->lockMode) {
$this->beginTransaction();
switch ($this->driver) {
case 'mysql':
case 'oci':
case 'pgsql':
return "SELECT $this->dataCol, $this->lifetimeCol FROM $this->table WHERE $this->idCol = :id FOR UPDATE";
case 'sqlsrv':
return "SELECT $this->dataCol, $this->lifetimeCol FROM $this->table WITH (UPDLOCK, ROWLOCK) WHERE $this->idCol = :id";
case 'sqlite':
// we already locked when starting transaction
break;
default:
throw new \DomainException(\sprintf('Transactional locks are currently not implemented for PDO driver "%s".', $this->driver));
}
}
return "SELECT $this->dataCol, $this->lifetimeCol FROM $this->table WHERE $this->idCol = :id";
}
/**
* Returns an insert statement supported by the database for writing session data.
*/
private function getInsertStatement(#[\SensitiveParameter] string $sessionId, string $sessionData, int $maxlifetime): \PDOStatement
{
switch ($this->driver) {
case 'oci':
$data = fopen('php://memory', 'r+');
fwrite($data, $sessionData);
rewind($data);
$sql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, EMPTY_BLOB(), :expiry, :time) RETURNING $this->dataCol into :data";
break;View on GitHub (pinned to 5aea19cd67)