getgrav/grav · error · RuntimeException
json_encode(): failed to encode group permissions
Error message
json_encode(): failed to encode group permissions
What it means
When a form asks FlexPageObject for 'header.permissions.groups', the value is round-tripped through json_encode() to normalize it; if encoding fails (false), Grav throws this RuntimeException. json_encode() fails on invalid UTF-8 sequences, resources, INF/NAN floats, or deeply recursive arrays. The permissions data itself is malformed for JSON, usually because the page frontmatter or a custom permission resolver produced non-encodable values.
Source
Thrown at system/src/Grav/Framework/Flex/Pages/FlexPageObject.php:206
*/
public function getFormValue(string $name, $default = null, ?string $separator = null)
{
$test = new stdClass();
$value = $this->pageContentValue($name, $test);
if ($value !== $test) {
return $value;
}
switch ($name) {
case 'name':
return $this->getProperty('template');
case 'route':
return $this->hasKey() ? '/' . $this->getKey() : null;
case 'header.permissions.groups':
$encoded = json_encode($this->getPermissions());
if ($encoded === false) {
throw new RuntimeException('json_encode(): failed to encode group permissions');
}
return json_decode($encoded, true);
}
return parent::getFormValue($name, $default, $separator);
}
/**
* Get master storage key.
*
* @return string
* @see FlexObjectInterface::getStorageKey()
*/
public function getMasterKey(): string
{
$key = (string)($this->storage_key ?? $this->getMetaData()['storage_key'] ?? null);
if (($pos = strpos($key, '|')) !== false) {View on GitHub (pinned to 6040efed04)
Solutions
- Fix the source data: ensure header.permissions.groups in the page file uses valid UTF-8 strings and plain arrays.
- json_last_error() after a failed encode to identify the cause (JSON_ERROR_UTF8 vs JSON_ERROR_RECURSION etc.) and strip/sanitize accordingly (mb_convert_encoding, removing resources).
- If a plugin modifies permissions at runtime, make it return scalar arrays of permission strings only.
- Catch the RuntimeException around form rendering to degrade gracefully with an admin notice instead of a 500.
Example fix
// before (frontmatter)
permissions:
groups:
site-editors: ["\xB1-invalid-utf8"]
# after
permissions:
groups:
site-editors: ["pages.read", "pages.update"] Defensive patterns
Strategy: try-catch
Validate before calling
// Validate group permissions are JSON-safe before rendering forms
$groups = $page->getPermissions();
if (json_encode($groups) === false) {
// identify cause: json_last_error_msg(); sanitize invalid UTF-8, drop resources
$groups = array_map(
fn($v) => is_string($v) ? mb_convert_encoding($v, 'UTF-8', 'UTF-8') : $v,
$groups
);
} Try / catch
try {
$value = $page->getFormValue('header.permissions.groups');
} catch (\Grav\Framework\Flex\Exception\RuntimeException $e) {
// permissions data not JSON-encodable: flag the page for repair instead of a hard 500
$admin->setMessage('Page ' . $page->route() . ' has malformed permissions data', 'error');
} Prevention
- Keep permissions.groups values as plain arrays of permission strings in valid UTF-8.
- Edit frontmatter in UTF-8 editors only.
- If plugins alter permissions at runtime, have them return scalars/arrays, never resources or objects.
When it happens
Trigger: Page header permissions.groups containing invalid UTF-8 bytes (pasted binary/smart characters from a bad editor); a plugin injecting resources or objects into group permission arrays; group values containing NAN/INF from arithmetic; array recursion from self-referencing permission structures.
Common situations: Frontmatter edited in a non-UTF-8 editor or copied from word processors; third-party access-control plugins that attach runtime objects to permission groups.
Related errors
- json_encode(): failed to encode dependencies
- Encoding JSON failed: {json_last_error_msg}
- ZipArchiver: ZIP failed to extract {archive_file} to {destin
- Bad child
- Invalid argument $value
AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17).
Data as JSON: /api/errors/c6a73cc95fd679c2.
Report an issue: GitHub.