getgrav/grav · error · RuntimeException
Decoding serialized data failed
Error message
Decoding serialized data failed
What it means
Grav's SerializeFormatter::decode() calls PHP's unserialize() (with notices suppressed) and throws this RuntimeException when unserialize() returns false for input that is not literally serialize(false). It means the byte stream handed to the formatter is not valid, complete PHP-serialized data. Typical root causes are truncated or hand-edited files, line-ending/encoding mangling during transfer, or data produced by a different serializer.
Source
Thrown at system/src/Grav/Framework/File/Formatter/SerializeFormatter.php:71
* {@inheritdoc}
* @see FileFormatterInterface::encode()
*/
public function encode($data): string
{
return serialize($this->preserveLines($data, ["\n", "\r"], ['\\n', '\\r']));
}
/**
* {@inheritdoc}
* @see FileFormatterInterface::decode()
*/
public function decode($data)
{
$classes = $this->getOptions()['allowed_classes'] ?? false;
$decoded = @unserialize($data, ['allowed_classes' => $classes]);
if ($decoded === false && $data !== serialize(false)) {
throw new RuntimeException('Decoding serialized data failed');
}
return $this->preserveLines($decoded, ['\\n', '\\r'], ["\n", "\r"]);
}
/**
* Preserve new lines, recursive function.
*
* @param array $search
* @param array $replace
* @return mixed
*/
protected function preserveLines(mixed $data, array $search, array $replace)
{
if (is_string($data)) {
$data = str_replace($search, $replace, $data);
} elseif (is_array($data)) {
foreach ($data as &$value) {View on GitHub (pinned to 6040efed04)
Solutions
- Delete or restore the offending serialized file so Grav regenerates it from defaults (check user/data, user/cache, backup directories).
- Verify the file was not modified: compare length/checksum against a backup; re-export rather than hand-edit serialized data.
- If the file legitimately contains another format, configure the correct formatter (JsonFormatter/YamlFormatter) for that file instead of SerializeFormatter.
- Wrap decode() in a try-catch that treats unreadable data as 'file missing' and rebuilds it.
Example fix
// before
$data = $file->load(); // RuntimeException: Decoding serialized data failed
// after
try {
$data = $file->load();
} catch (RuntimeException $e) {
@unlink($file->filename()); // discard corrupt state, rebuild
$data = $defaults;
$file->save($data);
} Defensive patterns
Strategy: try-catch
Validate before calling
// Cheap pre-check: valid serialized streams start with a type token
if (!is_string($data) || $data === '' || !preg_match('/^[a-zOCdbsiNa]:\d+/i', $data)) {
// not serialized data; skip decode or rebuild defaults
} Try / catch
try {
$decoded = $formatter->decode($data);
} catch (\Grav\Framework\File\Formatter\Exception\RuntimeException $e) {
// treat as corrupt: log, restore defaults, and continue
$decoded = $defaults;
$log->warning('Corrupt serialized file {file}: {msg}', ['file' => $filename, 'msg' => $e->getMessage()]);
} Prevention
- Never hand-edit serialized files; regenerate them programmatically.
- Keep serialized state files out of editors/FTP ASCII transfers; deploy archives instead.
- Prefer JsonFormatter or YamlFormatter for user-visible data — they fail with clearer errors.
- Back up the data directory so corrupt state can be restored.
When it happens
Trigger: Reading a saved .serialized cache/state file that was corrupted, emptied, or truncated; calling $formatter->decode() on a string that was never produced by serialize() (e.g. JSON or plain text); transferring serialized files in a way that converts \n/\r or strips bytes; a file written by an incompatible PHP serialization format.
Common situations: Deploying or copying the grav data/cache directories between servers with FTP in ASCII mode; a cache cleaner or editor truncating files under user/data; switching a file's formatter configuration from JsonFormatter to SerializeFormatter while old files still contain the previous format.
Related errors
- Failed to save file '%s': %s
- Encoding JSON failed: {json_last_error_msg}
- Bad data
- Cannot unserialize Block: %s
- Unsupported version %s
AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17).
Data as JSON: /api/errors/078fb3b21bca8ec1.
Report an issue: GitHub.