getgrav/grav · error · RuntimeException
Unsupported version %s
Error message
Unsupported version %s
What it means
ContentBlock::checkVersion() runs at the top of build(): it reads '_version' from the serialized array (defaulting to 1) and requires it to equal the block class's own $version. A mismatch throws RuntimeException('Unsupported version N') — a format-compatibility guard that rejects block data serialized by a different Grav release instead of silently misinterpreting it. It normally reaches callers wrapped as 'Cannot unserialize Block: Unsupported version N'.
Source
Thrown at system/src/Grav/Framework/ContentBlock/ContentBlock.php:300
/**
* @return string
*/
protected function generateId()
{
return uniqid('', true);
}
/**
* @param array $serialized
* @return void
* @throws RuntimeException
*/
protected function checkVersion(array $serialized)
{
$version = isset($serialized['_version']) ? (int) $serialized['_version'] : 1;
if ($version !== $this->version) {
throw new RuntimeException(sprintf('Unsupported version %s', $version));
}
}
}
View on GitHub (pinned to 6040efed04)
Solutions
- Clear the cache after every Grav upgrade: bin/grav clear-cache (or remove the cache/* directories).
- Verify all servers/environments run the same Grav version so serialized '_version' values match.
- Treat serialized blocks as disposable cache: catch the RuntimeException and regenerate the block from source content.
- If you persist block arrays yourself, key them by Grav version and discard old keys on upgrade.
Example fix
// before
$block = ContentBlock::fromArray($cached);
// after
try {
$block = ContentBlock::fromArray($cached);
} catch (\RuntimeException $e) {
// stale cache with a different block format version: drop and regenerate
$cache->delete($key);
$block = ContentBlock::fromArray($fresh->toArray());
} Defensive patterns
Strategy: try-catch
Validate before calling
// Compare stored format version against the running version before fromArray()
$expected = (int) ($freshBlock->toArray()['_version'] ?? 1);
if ((int) ($serialized['_version'] ?? 1) !== $expected) {
$serialized = $freshBlock->toArray(); // regenerate instead of unserializing
} Try / catch
try {
$block = ContentBlock::fromArray($cached);
} catch (\RuntimeException $e) {
if (str_contains($e->getMessage(), 'Unsupported version')) {
$cache->delete($key); // stale format: drop and rebuild
$block = ContentBlock::fromArray($fresh->toArray());
} else {
throw $e;
}
} Prevention
- Clear the cache after every Grav upgrade — serialized block format changes with releases.
- Keep all nodes in multi-server setups on the same Grav version.
- Never persist block arrays longer-term than the version that wrote them.
When it happens
Trigger: fromArray()/build() receives arrays whose '_version' differs from the running class's version: cache serialized before a Grav upgrade replayed after it; data written by a newer Grav read by an older install (rollback); block arrays persisted long-term (DB/session) instead of being treated as disposable cache.
Common situations: Deploying a new Grav version without clearing cache; rolling back a release while the cache survives; multi-server setups running mixed Grav versions behind one cache backend; importing cache or backups from another environment.
Related errors
- Bad data
- Cannot unserialize Block: %s
- Creating directory failed for {filepath}
- Opening file for writing failed on error {$message}
- Failed to save file {filepath}
AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17).
Data as JSON: /api/errors/10d5148eabc34109.
Report an issue: GitHub.