{"record":{"id":"da97c66e39c3a4ac","repo":"symfony/http-foundation","slug":"sqlite-does-not-support-advisory-locks","errorCode":null,"errorMessage":"SQLite does not support advisory locks.","messagePattern":"SQLite does not support advisory locks\\.","errorType":"exception","errorClass":"DomainException","httpStatus":null,"severity":"error","filePath":"Session/Storage/Handler/PdoSessionHandler.php","lineNumber":805,"sourceCode":"                    $stmt->execute();\n\n                    $releaseStmt = $this->pdo->prepare('SELECT pg_advisory_unlock(:key1, :key2)');\n                    $releaseStmt->bindValue(':key1', $sessionInt1, \\PDO::PARAM_INT);\n                    $releaseStmt->bindValue(':key2', $sessionInt2, \\PDO::PARAM_INT);\n                } else {\n                    $sessionBigInt = $this->convertStringToInt($sessionId);\n\n                    $stmt = $this->pdo->prepare('SELECT pg_advisory_lock(:key)');\n                    $stmt->bindValue(':key', $sessionBigInt, \\PDO::PARAM_INT);\n                    $stmt->execute();\n\n                    $releaseStmt = $this->pdo->prepare('SELECT pg_advisory_unlock(:key)');\n                    $releaseStmt->bindValue(':key', $sessionBigInt, \\PDO::PARAM_INT);\n                }\n\n                return $releaseStmt;\n            case 'sqlite':\n                throw new \\DomainException('SQLite does not support advisory locks.');\n            default:\n                throw new \\DomainException(\\sprintf('Advisory locks are currently not implemented for PDO driver \"%s\".', $this->driver));\n        }\n    }\n\n    /**\n     * Encodes the first 4 (when PHP_INT_SIZE == 4) or 8 characters of the string as an integer.\n     *\n     * Keep in mind, PHP integers are signed.\n     */\n    private function convertStringToInt(string $string): int\n    {\n        if (4 === \\PHP_INT_SIZE) {\n            return (\\ord($string[3]) << 24) + (\\ord($string[2]) << 16) + (\\ord($string[1]) << 8) + \\ord($string[0]);\n        }\n\n        $int1 = (\\ord($string[7]) << 24) + (\\ord($string[6]) << 16) + (\\ord($string[5]) << 8) + \\ord($string[4]);\n        $int2 = (\\ord($string[3]) << 24) + (\\ord($string[2]) << 16) + (\\ord($string[1]) << 8) + \\ord($string[0]);","sourceCodeStart":787,"sourceCodeEnd":823,"githubUrl":"https://github.com/symfony/http-foundation/blob/5aea19cd678fa4140f6108406f1096de5e9ed6e4/Session/Storage/Handler/PdoSessionHandler.php#L787-L823","documentation":"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.","triggerScenarios":"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()).","commonSituations":"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.","solutions":["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.","Switch the session store to the production database (mysql/pgsql DSN) if advisory locking semantics are genuinely needed.","Use PdoSessionHandler::LOCK_TRANSACTIONAL instead, which is supported for sqlite (locking is done via the transaction: 'we already locked when starting transaction').","Differentiate config per environment: define lock_mode only for drivers that support advisory locks (mysql, pgsql)."],"exampleFix":"// before\n$handler = new PdoSessionHandler($pdo, ['lock_mode' => PdoSessionHandler::LOCK_ADVISORY]);\n\n// after (sqlite)\n$handler = new PdoSessionHandler($pdo, ['lock_mode' => PdoSessionHandler::LOCK_TRANSACTIONAL]);","handlingStrategy":"validation","validationCode":"$driver = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);\nif ('sqlite' === $driver && ($options['lock_mode'] ?? null) === PdoSessionHandler::LOCK_ADVISORY) {\n    unset($options['lock_mode']); // or use LOCK_TRANSACTIONAL\n}","typeGuard":null,"tryCatchPattern":"try {\n    $session->start();\n} catch (\\DomainException $e) {\n    if (str_contains($e->getMessage(), 'does not support advisory locks')) {\n        // rebuild handler with LOCK_TRANSACTIONAL or LOCK_NONE\n    } else {\n        throw $e;\n    }\n}","preventionTips":["Never set LOCK_ADVISORY for sqlite DSNs; gate lock_mode on driver name","Use environment-specific session handler config (dev sqlite vs prod mysql/pgsql)","Remember sqlite needs no advisory lock — its file locking already serializes writers"],"tags":["sessions","pdo","sqlite","configuration","locking"],"backgroundTag":"unsupported-operation","analyzedSha":"5aea19cd678fa4140f6108406f1096de5e9ed6e4","analyzedAt":"2026-09-13T01:52:22.855Z","contentChangedAt":"2026-09-13T01:52:22.855Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}