{"record":{"id":"6c511491f7e877bd","repo":"getgrav/grav","slug":"failed-to-load-file-s-s","errorCode":null,"errorMessage":"Failed to load file '%s': %s","messagePattern":"Failed to load file '(.+?)': (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"system/src/Grav/Framework/File/DataFile.php","lineNumber":54,"sourceCode":"        $this->formatter = $formatter;\n    }\n\n    /**\n     * {@inheritdoc}\n     * @see FileInterface::load()\n     */\n    public function load()\n    {\n        $raw = parent::load();\n\n        try {\n            if (!is_string($raw)) {\n                throw new RuntimeException('Bad Data');\n            }\n\n            return $this->formatter->decode($raw);\n        } catch (RuntimeException $e) {\n            throw new RuntimeException(sprintf(\"Failed to load file '%s': %s\", $this->getFilePath(), $e->getMessage()), $e->getCode(), $e);\n        }\n    }\n\n    /**\n     * {@inheritdoc}\n     * @see FileInterface::save()\n     */\n    public function save($data): void\n    {\n        if (is_string($data)) {\n            // Make sure that the string is valid data.\n            try {\n                $this->formatter->decode($data);\n            } catch (RuntimeException $e) {\n                throw new RuntimeException(sprintf(\"Failed to save file '%s': %s\", $this->getFilePath(), $e->getMessage()), $e->getCode(), $e);\n            }\n            $encoded = $data;\n        } else {","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/getgrav/grav/blob/6040efed04efa69b8209448ed81308e7c24147c2/system/src/Grav/Framework/File/DataFile.php#L36-L72","documentation":"DataFile::load() wraps every read-or-decode failure into this message: the file path plus the underlying reason. The inner exception is either 'Bad Data' (raw read returned false — missing/unreadable file) or any RuntimeException from the configured formatter (invalid JSON/YAML/INI/CSV syntax). The original is chained, so $e->getPrevious() tells you whether the problem was I/O or parsing.","triggerScenarios":"Loading a data file with a syntax error for its format (bad JSON/YAML/INI/CSV); a missing or unreadable file (surfaces as '...: Bad Data'); a file whose extension maps to a different formatter than its actual content (JSON content in a .yaml file).","commonSituations":"Hand-edited plugin configuration with a typo (missing comma/quote); files truncated by a crash mid-save; BOM or smart quotes pasted from documentation; deploying files edited with wrong encoding; wrong extension-to-formatter mapping in configuration.","solutions":["Read the message: the quoted path identifies the file; the tail gives the reason ('Bad Data' = read failure, anything else = parse error with position).","Validate the file in isolation: php -r 'json_decode(file_get_contents(\"f.json\")); echo json_last_error_msg();' (or a YAML/INI linter) and fix the reported line.","If the tail is 'Bad Data', fix existence/readability of the file (see the file-read family).","Restore from backup or delete the file so Grav regenerates defaults; make sure the extension matches the content format."],"exampleFix":"# before: RuntimeException \"Failed to load file 'user/data/x.json': Syntax error\"\nphp -r 'json_decode(file_get_contents(\"user/data/x.json\")); echo json_last_error_msg(), PHP_EOL;'\n# -> Syntax error  (fix the reported construct, e.g. trailing comma)\n# after: $dataFile->load() succeeds","handlingStrategy":"try-catch","validationCode":"$path = $dataFile->getFilePath();\nif (is_file($path) && is_readable($path)) {\n    $raw = file_get_contents($path);\n    if (is_string($raw) && in_array($ext, ['json'], true) \n        && json_decode($raw) === null && json_last_error() !== JSON_ERROR_NONE) {\n        // syntax problem: fix the file before calling load()\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    $data = $dataFile->load();\n} catch (\\RuntimeException $e) {\n    // path + reason are in the message; previous exception distinguishes I/O vs parse\n    $log->error($e->getMessage());\n    $data = $defaults; // or quarantine the file for manual repair\n}","preventionTips":["Lint all data/config files in CI so syntax errors never deploy.","Write files via the formatter's save() rather than manual edits.","Reject BOM and smart quotes at input boundaries."],"tags":["php","grav","file-io","parse-error","data-file","wrapper-exception"],"backgroundTag":"file-parse-failed","analyzedSha":"6040efed04efa69b8209448ed81308e7c24147c2","analyzedAt":"2026-08-17T05:07:31.593Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}