{"record":{"id":"da25a94abf466bda","repo":"getgrav/grav","slug":"decoding-json-failed-json-last-error-msg","errorCode":null,"errorMessage":"Decoding JSON failed: {json_last_error_msg}","messagePattern":"Decoding JSON failed: (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"system/src/Grav/Framework/File/Formatter/JsonFormatter.php","lineNumber":165,"sourceCode":"        $encoded = @json_encode($data, $this->getEncodeOptions());\n\n        if ($encoded === false && json_last_error() !== JSON_ERROR_NONE) {\n            throw new RuntimeException('Encoding JSON failed: ' . json_last_error_msg());\n        }\n\n        return $encoded ?: '';\n    }\n\n    /**\n     * {@inheritdoc}\n     * @see FileFormatterInterface::decode()\n     */\n    public function decode($data)\n    {\n        $decoded = @json_decode($data, $this->getDecodeAssoc(), $this->getDecodeDepth(), $this->getDecodeOptions());\n\n        if (null === $decoded && json_last_error() !== JSON_ERROR_NONE) {\n            throw new RuntimeException('Decoding JSON failed: ' . json_last_error_msg());\n        }\n\n        return $decoded;\n    }\n}\n","sourceCodeStart":147,"sourceCodeEnd":171,"githubUrl":"https://github.com/getgrav/grav/blob/6040efed04efa69b8209448ed81308e7c24147c2/system/src/Grav/Framework/File/Formatter/JsonFormatter.php#L147-L171","documentation":"JsonFormatter::decode() calls @json_decode($data, $assoc, $depth, $options) and throws when the result is null and json_last_error() reports an error: syntax errors (truncation, trailing commas, single quotes, comments), malformed UTF-8, or nesting deeper than the configured decode depth. A file whose entire content is literal null decodes to null without an error and returns normally — the json_last_error() check distinguishes that case.","triggerScenarios":"Loading a .json file with a syntax error; truncated files from an interrupted write; a UTF-8 BOM at the start (json_decode rejects it); nesting beyond decode depth; JSON with // comments or trailing commas from hand editing.","commonSituations":"Hand-edited site/plugin configuration; editors saving with BOM; partially uploaded files; JSON built by string concatenation; deep structures hitting the default 512 depth.","solutions":["Locate the error: php -r 'json_decode(file_get_contents(\"f.json\")); echo json_last_error_msg();' or jq . f.json, then fix the reported construct.","Strip a leading BOM: $data = preg_replace('/^\\xEF\\xBB\\xBF/', '', $data).","Remove JSON-invalid syntax: comments, trailing commas, single-quoted strings.","If the nesting is legitimate, increase decode_depth in the JSON formatter/file configuration."],"exampleFix":"# before: RuntimeException \"Decoding JSON failed: Syntax error\"\njq . user/data/broken.json    # pinpoints the parse error\n# fix the reported line (e.g. remove trailing comma), then:\n# $dataFile->load() succeeds","handlingStrategy":"validation","validationCode":"// PHP 8.3+: cheap syntax gate\nif (function_exists('json_validate') && !json_validate($raw)) {\n    // fix the payload before JsonFormatter::decode()\n}\n// older PHP: trial decode\njson_decode($raw);\nif (json_last_error() !== JSON_ERROR_NONE) { /* handle */ }","typeGuard":null,"tryCatchPattern":"try {\n    $data = $jsonFormatter->decode($raw);\n} catch (\\RuntimeException $e) {\n    // json_last_error_msg() is embedded; fall back to defaults and flag the file\n    $data = $defaults;\n    $log->error($e->getMessage());\n}","preventionTips":["Lint every JSON file in CI (jq, json_decode checks).","Strip BOMs when ingesting external JSON.","Edit data files through the formatter's save() rather than by hand."],"tags":["php","grav","json","parse-error","utf-8-bom","config"],"backgroundTag":"json-parse-error","analyzedSha":"6040efed04efa69b8209448ed81308e7c24147c2","analyzedAt":"2026-08-17T05:07:31.593Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}