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

  1. Clear the cache after every Grav upgrade: bin/grav clear-cache (or remove the cache/* directories).
  2. Verify all servers/environments run the same Grav version so serialized '_version' values match.
  3. Treat serialized blocks as disposable cache: catch the RuntimeException and regenerate the block from source content.
  4. 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

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


AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17). Data as JSON: /api/errors/10d5148eabc34109. Report an issue: GitHub.