getgrav/grav · error · RuntimeException
json_encode(): failed to encode dependencies
Error message
json_encode(): failed to encode dependencies
What it means
While compiling permission definitions, PermissionsReader normalizes its dependency tree by round-tripping it through json_encode/json_decode. json_encode() returns false when the payload contains data PHP cannot serialize — invalid UTF-8 sequences, resources, INF/NAN, or circular references — and that failure is rethrown as this RuntimeException. The bad data ultimately comes from permission metadata (labels, descriptions, dependency maps) contributed by plugins.
Source
Thrown at system/src/Grav/Framework/Acl/PermissionsReader.php:118
$current[$defaults['type']] = null;
}
$dependencies[$type] = (object)$current;
}
// Build dependency tree.
foreach ($dependencies as $type => $dep) {
foreach (get_object_vars($dep) as $k => &$val) {
if (null === $val) {
$val = $dependencies[$k] ?? new stdClass();
}
}
unset($val);
}
$encoded = json_encode($dependencies);
if ($encoded === false) {
throw new RuntimeException('json_encode(): failed to encode dependencies');
}
$dependencies = json_decode($encoded, true);
foreach (static::getDependencies($dependencies) as $type) {
$defaults = $types[$type] ?? null;
if ($defaults) {
static::$types[$type] = static::addDefaults($defaults);
}
}
}
/**
* @param array $dependencies
* @return array
*/
protected static function getDependencies(array $dependencies): array
{
$list = [[]];View on GitHub (pinned to 6040efed04)
Solutions
- Identify the offending plugin: disable recently added plugins one by one (or bisect) and re-trigger permission compilation to isolate which YAML is unserializable.
- Re-save the plugin's permissions.yaml explicitly as UTF-8 without BOM; replace smart quotes/dashes with plain ASCII or proper UTF-8.
- If you build permission data in code, ensure only scalars/arrays (no closures, resources, objects with circular refs) enter labels, descriptions, and dependencies.
- Run json_last_error() diagnostics on a minimal reproduction of the YAML payload to confirm the exact cause (malformed UTF-8 vs recursion).
Example fix
# user/plugins/myplugin/permissions.yaml (before: saved as Windows-1252) # access: # admin.myplugin: # label: "It’s broken…" # non-UTF-8 bytes -> json_encode fails # after: re-encode file to UTF-8 # admin.myplugin: # label: "It's fixed..." # plain UTF-8/ASCII
Defensive patterns
Strategy: validation
Validate before calling
// validate plugin permission strings are UTF-8-clean before install
$yaml = file_get_contents('user/plugins/myplugin/permissions.yaml');
if (!mb_check_encoding($yaml, 'UTF-8')) {
exit('permissions.yaml is not valid UTF-8; re-save the file as UTF-8' . PHP_EOL);
}
if (json_encode(json_decode(json_encode(yaml_parse($yaml) ?? []))) === false) {
exit('Permission data not JSON-serializable: ' . json_last_error_msg() . PHP_EOL);
} Try / catch
try {
PermissionsReader::read(...);
} catch (\RuntimeException $e) {
if (str_contains($e->getMessage(), 'json_encode')) {
// bisect: disable newest plugins until compilation succeeds
error_log('Unserializable permission metadata; check plugin YAML encoding');
}
throw;
} Prevention
- Save all plugin YAML as UTF-8 without BOM; avoid smart quotes in labels/descriptions.
- Run mb_check_encoding() on imported permission files during CI.
- Keep only scalars and arrays in permission metadata — no closures, resources, or circular references.
When it happens
Trigger: A plugin's permissions.yaml (or plugin-defined permission arrays) containing non-UTF-8 bytes (Windows-1252 curly quotes, BOM-pasted text) that end up in dependency values; a plugin programmatically attaching a closure/resource into permission dependency data; YAML aliases creating circular structures in dependency objects.
Common situations: Plugin YAML edited in a non-UTF-8 editor on Windows; copy-pasting marketing text with smart quotes into permission descriptions; permissions cache warm-up failing during `bin/grav clearcache` or first admin request after installing a plugin; PHP version change surfacing previously-tolerated malformed strings.
Related errors
- Bad child
- json_encode(): failed to encode group permissions
- Could not migrate the Twig-sandbox allowlists to the additiv
- ZipArchiver: ZIP failed to extract {archive_file} to {destin
- Creating directory failed for {filepath}
AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17).
Data as JSON: /api/errors/0d300d4c009659c1.
Report an issue: GitHub.