getgrav/grav · error · InvalidArgumentException
Cache key length must be less than 65 characters, key had %d
Error message
Cache key length must be less than 65 characters, key had %d characters
What it means
Grav's cache key validator enforces the PSR-16 maximum key length of 64 characters. Keys longer than 64 chars throw InvalidArgumentException reporting the actual length, because many backends (memcached, some Redis setups, filesystem adapters) misbehave or truncate long keys.
Source
Thrown at system/src/Grav/Framework/Cache/CacheTrait.php:317
* @param string|mixed $key
* @return void
* @throws InvalidArgumentException
*/
protected function validateKey(mixed $key): void
{
if (!is_string($key)) {
throw new InvalidArgumentException(
sprintf(
'Cache key must be string, "%s" given',
get_debug_type($key)
)
);
}
if (!isset($key[0])) {
throw new InvalidArgumentException('Cache key length must be greater than zero');
}
if (strlen($key) > 64) {
throw new InvalidArgumentException(
sprintf('Cache key length must be less than 65 characters, key had %d characters', strlen($key))
);
}
if (strpbrk($key, '{}()/\@:') !== false) {
throw new InvalidArgumentException(
sprintf('Cache key "%s" contains reserved characters {}()/\@:', $key)
);
}
}
/**
* @param array $keys
* @return void
* @throws InvalidArgumentException
*/
protected function validateKeys(iterable $keys): void
{
if (!$this->validation) {View on GitHub (pinned to 6040efed04)
Solutions
- Hash long keys: $key = md5($rawKey) (optionally keep a short prefix: 'pg-' . md5($url)) — deterministic and always 32/40 chars.
- Extract a compact natural key first (page slug + language) and only hash when it overflows.
- Centralize key building in one helper that enforces the 64-char budget so every call site inherits it.
Example fix
// before
$cache->get('fragment-' . $uri . '?' . http_build_query($query)); // >64 chars -> throws
// after
$cache->get('fragment-' . md5($uri . '?' . http_build_query($query))); // 8+32 chars Defensive patterns
Strategy: validation
Validate before calling
if (strlen($key) > 64) {
$key = 'h-' . md5($key); // 34 chars, deterministic
}
$cache->get($key); Prevention
- Hash URL/path-derived keys with md5() unconditionally — simplest way to stay under budget.
- Keep a short readable prefix plus hash suffix ('pg-' . md5($uri)) for debuggability.
- Add a key-length assertion to your key-builder helper's tests.
When it happens
Trigger: Using full page URLs, long serialized parameter lists, or concatenated entity identifiers as raw keys (e.g. 'page-/very/long/nested/path/with?many=query¶ms=...'); composite keys built by joining every context variable; getMultiple with oversized members hitting validateKeys().
Common situations: Caching rendered fragments keyed by raw URI on content-heavy sites; multi-language sites prepending long locale+route prefixes; query-string-heavy listing pages producing unique but very long keys.
Related errors
- Cache key must be string, "%s" given
- Cache key length must be greater than zero
- Cache key "%s" contains reserved characters {}()/\@:
- The class '%s' does not implement the '%s' interface
- Cache keys must be array or Traversable, "%s" given
AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17).
Data as JSON: /api/errors/f631d8a7a12ab4ac.
Report an issue: GitHub.