{"record":{"id":"af5c6493f2099ce7","repo":"symfony/symfony","slug":"s-requires-pdo-error-mode-attribute-be-set-to-t","errorCode":null,"errorMessage":"\"%s\" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)).","messagePattern":"\"(.+?)\" requires PDO error mode attribute be set to throw Exceptions \\(i\\.e\\. \\$pdo->setAttribute\\(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION\\)\\)\\.","errorType":"exception","errorClass":"Symfony\\Component\\Cache\\Exception\\InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"src/Symfony/Component/Cache/Adapter/PdoAdapter.php","lineNumber":69,"sourceCode":"     *  * db_connection_options: An array of driver-specific connection options [default: []]\n     *\n     * @throws InvalidArgumentException When first argument is not PDO nor Connection nor string\n     * @throws InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION\n     * @throws InvalidArgumentException When namespace contains invalid characters\n     */\n    public function __construct(#[\\SensitiveParameter] \\PDO|string $connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], ?MarshallerInterface $marshaller = null)\n    {\n        if (\\is_string($connOrDsn) && str_contains($connOrDsn, '://')) {\n            throw new InvalidArgumentException(\\sprintf('Usage of Doctrine DBAL URL with \"%s\" is not supported. Use a PDO DSN or \"%s\" instead.', __CLASS__, DoctrineDbalAdapter::class));\n        }\n\n        if (isset($namespace[0]) && preg_match('#[^-+.A-Za-z0-9]#', $namespace, $match)) {\n            throw new InvalidArgumentException(\\sprintf('Namespace contains \"%s\" but only characters in [-+.A-Za-z0-9] are allowed.', $match[0]));\n        }\n\n        if ($connOrDsn instanceof \\PDO) {\n            if (\\PDO::ERRMODE_EXCEPTION !== $connOrDsn->getAttribute(\\PDO::ATTR_ERRMODE)) {\n                throw new InvalidArgumentException(\\sprintf('\"%s\" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)).', __CLASS__));\n            }\n\n            $this->conn = $connOrDsn;\n        } else {\n            $this->dsn = $connOrDsn;\n        }\n\n        $this->maxIdLength = self::MAX_KEY_LENGTH;\n        $this->table = $options['db_table'] ?? $this->table;\n        $this->idCol = $options['db_id_col'] ?? $this->idCol;\n        $this->dataCol = $options['db_data_col'] ?? $this->dataCol;\n        $this->lifetimeCol = $options['db_lifetime_col'] ?? $this->lifetimeCol;\n        $this->timeCol = $options['db_time_col'] ?? $this->timeCol;\n        $this->username = $options['db_username'] ?? $this->username;\n        $this->password = $options['db_password'] ?? $this->password;\n        $this->connectionOptions = $options['db_connection_options'] ?? $this->connectionOptions;\n        $this->namespace = $namespace;\n        $this->marshaller = $marshaller ?? new DefaultMarshaller();","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/symfony/symfony/blob/698e28026c22cf35d032cdb6e800db48b1535790/src/Symfony/Component/Cache/Adapter/PdoAdapter.php#L51-L87","documentation":"PdoAdapter requires that any PDO instance passed to its constructor be configured to throw exceptions on error (PDO::ERRMODE_EXCEPTION). The adapter relies on exceptions to detect failed statements and report them; in the default silent mode PDO returns false instead, which would corrupt cache reads/writes silently. The constructor checks the attribute at src/Symfony/Component/Cache/Adapter/PdoAdapter.php:67-70 and rejects the connection if it is not set.","triggerScenarios":"Constructing `new PdoAdapter($pdo, $namespace, $lifetime)` where `$pdo` is a pre-existing \\PDO instance that was NOT configured with `$pdo->setAttribute(\\PDO::ATTR_ERRMODE, \\PDO::ERRMODE_EXCEPTION)`. Passing a DSN string does NOT trigger this (the adapter sets the mode itself via createConnection).","commonSituations":"Sharing a single PDO connection created elsewhere (Doctrine DBAL, a legacy bootstrap, or a manual `new \\PDO($dsn)` with default ERRMODE_SILENT). Common when reusing the app's main DB connection for caching to save connections, or after upgrading the cache component which tightened this check.","solutions":["Set `$pdo->setAttribute(\\PDO::ATTR_ERRMODE, \\PDO::ERRMODE_EXCEPTION)` before passing the PDO instance to the adapter.","Pass a DSN string instead of a PDO instance and let PdoAdapter::createConnection configure the error mode for you.","Use PdoAdapter::createConnection($dsn) which returns a properly configured PDO, then pass that."],"exampleFix":"// before\n$pdo = new \\PDO($dsn);\n$cache = new PdoAdapter($pdo, 'ns', 3600);\n\n// after\n$pdo = new \\PDO($dsn);\n$pdo->setAttribute(\\PDO::ATTR_ERRMODE, \\PDO::ERRMODE_EXCEPTION);\n$cache = new PdoAdapter($pdo, 'ns', 3600);","handlingStrategy":"validation","validationCode":"// Run before constructing the adapter\nif ($pdo instanceof \\PDO && \\PDO::ERRMODE_EXCEPTION !== $pdo->getAttribute(\\PDO::ATTR_ERRMODE)) {\n    $pdo->setAttribute(\\PDO::ATTR_ERRMODE, \\PDO::ERRMODE_EXCEPTION);\n}\n$cache = new PdoAdapter($pdo, $namespace, $lifetime);","typeGuard":null,"tryCatchPattern":"try {\n    $cache = new PdoAdapter($pdo, $namespace, $lifetime);\n} catch (\\Symfony\\Component\\Cache\\Exception\\InvalidArgumentException $e) {\n    // The PDO connection is misconfigured; set the attribute and retry,\n    // or fall back to passing a DSN string.\n    $pdo->setAttribute(\\PDO::ATTR_ERRMODE, \\PDO::ERRMODE_EXCEPTION);\n    $cache = new PdoAdapter($pdo, $namespace, $lifetime);\n}","preventionTips":["Centralize PDO creation in a factory that always sets ERRMODE_EXCEPTION.","Prefer passing a DSN string to PdoAdapter so it manages error mode itself.","Document which connections are safe to share with the cache pool."],"tags":["cache","pdo","configuration","constructor"],"analyzedSha":"698e28026c22cf35d032cdb6e800db48b1535790","analyzedAt":"2026-08-06T23:40:49.025Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}