symfony/symfony · error · Symfony\Component\Cache\Exception\InvalidArgumentException

Namespace contains "%s" but only characters in [-+.A-Za-z0-9

Error message

Namespace contains "%s" but only characters in [-+.A-Za-z0-9] are allowed.

What it means

Thrown by PdoAdapter's constructor (PdoAdapter.php:63) when the $namespace contains any character outside [-+.A-Za-z0-9]. Like DoctrineDbalAdapter, the namespace is interpolated into raw SQL LIKE patterns for clear/fetch, so unsafe characters are rejected to prevent query breakage and injection.

Source

Thrown at src/Symfony/Component/Cache/Adapter/PdoAdapter.php:64

     *  * db_data_col: The column where to store the cache data [default: item_data]
     *  * db_lifetime_col: The column where to store the lifetime [default: item_lifetime]
     *  * db_time_col: The column where to store the timestamp [default: item_time]
     *  * db_username: The username when lazy-connect [default: '']
     *  * db_password: The password when lazy-connect [default: '']
     *  * db_connection_options: An array of driver-specific connection options [default: []]
     *
     * @throws InvalidArgumentException When first argument is not PDO nor Connection nor string
     * @throws InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION
     * @throws InvalidArgumentException When namespace contains invalid characters
     */
    public function __construct(#[\SensitiveParameter] \PDO|string $connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], ?MarshallerInterface $marshaller = null)
    {
        if (\is_string($connOrDsn) && str_contains($connOrDsn, '://')) {
            throw new InvalidArgumentException(\sprintf('Usage of Doctrine DBAL URL with "%s" is not supported. Use a PDO DSN or "%s" instead.', __CLASS__, DoctrineDbalAdapter::class));
        }

        if (isset($namespace[0]) && preg_match('#[^-+.A-Za-z0-9]#', $namespace, $match)) {
            throw new InvalidArgumentException(\sprintf('Namespace contains "%s" but only characters in [-+.A-Za-z0-9] are allowed.', $match[0]));
        }

        if ($connOrDsn instanceof \PDO) {
            if (\PDO::ERRMODE_EXCEPTION !== $connOrDsn->getAttribute(\PDO::ATTR_ERRMODE)) {
                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__));
            }

            $this->conn = $connOrDsn;
        } else {
            $this->dsn = $connOrDsn;
        }

        $this->maxIdLength = self::MAX_KEY_LENGTH;
        $this->table = $options['db_table'] ?? $this->table;
        $this->idCol = $options['db_id_col'] ?? $this->idCol;
        $this->dataCol = $options['db_data_col'] ?? $this->dataCol;
        $this->lifetimeCol = $options['db_lifetime_col'] ?? $this->lifetimeCol;
        $this->timeCol = $options['db_time_col'] ?? $this->timeCol;

View on GitHub (pinned to 698e28026c)

Solutions

  1. Restrict the namespace to [-+.A-Za-z0-9] characters.
  2. Sanitize dynamic namespaces: $ns = preg_replace('/[^-+.A-Za-z0-9]/', '', $raw);
  3. Use dots or pluses for hierarchical separation instead of underscores/slashes.

Example fix

// before
new PdoAdapter($dsn, 'order_cache/v2');

// after
new PdoAdapter($dsn, 'order.cache.v2');
Defensive patterns

Strategy: validation

Validate before calling

if (preg_match('#[^-+.A-Za-z0-9]#', $namespace, $m)) {
    throw new \InvalidArgumentException('Invalid cache namespace char: '.$m[0]);
}
new PdoAdapter($dsn, $namespace);

Type guard

function isValidCacheNamespace(string $ns): bool
{
    return '' === $ns || 1 === preg_match('#^[-+.A-Za-z0-9]*$#', $ns);
}

Prevention

When it happens

Trigger: Calling `new PdoAdapter($dsn, 'my cache')` (space), `new PdoAdapter($dsn, 'a_b')` (underscore), or any namespace with slash/colon/etc. The regex '#[^-+.A-Za-z0-9]#' catches the first offender.

Common situations: Using a tenant id or app name with underscores/spaces as the cache namespace. Auto-derived namespaces from user input. Copying a namespace format used by a different adapter that allows underscores.

Related errors


AI-assisted analysis of symfony/symfony@698e28026c (2026-08-06). Data as JSON: /api/errors/837276eb8cbf2c6c. Report an issue: GitHub.