{"record":{"id":"fe8884b1b9456042","repo":"doctrine/cache","slug":"cache-key-s-contains-reserved-characters-s","errorCode":null,"errorMessage":"Cache key \"%s\" contains reserved characters \"%s\".","messagePattern":"Cache key \"(.+?)\" contains reserved characters \"(.+?)\"\\.","errorType":"exception","errorClass":"InvalidArgument","httpStatus":null,"severity":"error","filePath":"lib/Doctrine/Common/Cache/Psr6/CacheAdapter.php","lineNumber":265,"sourceCode":"    {\n        $this->commit();\n    }\n\n    /**\n     * @param mixed $key\n     */\n    private static function validKey($key): bool\n    {\n        if (! is_string($key)) {\n            throw new InvalidArgument(sprintf('Cache key must be string, \"%s\" given.', is_object($key) ? get_class($key) : gettype($key)));\n        }\n\n        if ($key === '') {\n            throw new InvalidArgument('Cache key length must be greater than zero.');\n        }\n\n        if (strpbrk($key, self::RESERVED_CHARACTERS) !== false) {\n            throw new InvalidArgument(sprintf('Cache key \"%s\" contains reserved characters \"%s\".', $key, self::RESERVED_CHARACTERS));\n        }\n\n        return true;\n    }\n\n    /**\n     * @param mixed[] $keys\n     */\n    private static function validKeys(array $keys): bool\n    {\n        foreach ($keys as $key) {\n            self::validKey($key);\n        }\n\n        return true;\n    }\n\n    /**","sourceCodeStart":247,"sourceCodeEnd":283,"githubUrl":"https://github.com/doctrine/cache/blob/e0a9919443c1e918251c23b65eddd9a66fafacb3/lib/Doctrine/Common/Cache/Psr6/CacheAdapter.php#L247-L283","documentation":"PSR-6 reserves the characters {}()/\\@: in cache keys, and Doctrine's CacheAdapter enforces this via strpbrk against self::RESERVED_CHARACTERS. validKey() throws InvalidArgument when a key passed to getItem/hasItem/deleteItem/deleteItems/validKeys contains any of them.","triggerScenarios":"Keys derived from file paths (/), emails (@), URLs (: /), class names with namespaces (\\), or templates ({}) passed directly to the pool.","commonSituations":"Caching by email address or file path; using FQCN as a key; concatenating a URI segment containing ':'; keys built from user-supplied URLs.","solutions":["Sanitize the key: replace reserved characters, e.g. preg_replace('/[{}()\\/\\\\@:]/', '_', $key)","Hash the offending value, e.g. md5() or sha1() of the raw identifier, to guarantee a safe key","Prefix with a safe namespace and keep only safe parts of the raw value in the key"],"exampleFix":"// before\n$item = $pool->getItem($email); // 'user@example.com'\n// after\n$item = $pool->getItem('email_' . md5($email));","handlingStrategy":"validation","validationCode":"if (strpbrk($key, '{}()/\\\\@:') !== false) { $key = preg_replace('/[{}()\\/\\\\@:]/', '_', $key); }","typeGuard":"function hasNoReservedChars(string $key): bool { return strpbrk($key, '{}()/\\\\@:') === false; }","tryCatchPattern":"try { $item = $pool->getItem($key); } catch (\\Doctrine\\Common\\Cache\\Psr6\\InvalidArgument $e) { $item = $pool->getItem(md5($rawKey)); }","preventionTips":["Hash email addresses, paths, URLs and FQCNs used as keys","Centralize key building in one sanitize helper","Know the PSR-6 reserved set: {}()/\\@:"],"tags":["psr6","cache","reserved-characters","psr-6"],"backgroundTag":"invalid-identifier-format","analyzedSha":"e0a9919443c1e918251c23b65eddd9a66fafacb3","analyzedAt":"2026-09-13T19:23:46.714Z","contentChangedAt":"2026-09-13T19:23:46.714Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}