getgrav/grav · error · RuntimeException

Bad Data

Error message

Bad Data

What it means

DataFile::load() reads raw bytes via parent::load() (file_get_contents) and requires a string; anything else throws 'Bad Data'. file_get_contents returns false exactly when the read failed — file missing, unreadable by the PHP user, or blocked by open_basedir — so despite the message the real cause is a failed read, not corrupt content. DataFile immediately re-wraps it as "Failed to load file '...': Bad Data" with this as the previous exception.

Source

Thrown at system/src/Grav/Framework/File/DataFile.php:49

     */
    public function __construct($filepath, FileFormatterInterface $formatter)
    {
        parent::__construct($filepath);

        $this->formatter = $formatter;
    }

    /**
     * {@inheritdoc}
     * @see FileInterface::load()
     */
    public function load()
    {
        $raw = parent::load();

        try {
            if (!is_string($raw)) {
                throw new RuntimeException('Bad Data');
            }

            return $this->formatter->decode($raw);
        } catch (RuntimeException $e) {
            throw new RuntimeException(sprintf("Failed to load file '%s': %s", $this->getFilePath(), $e->getMessage()), $e->getCode(), $e);
        }
    }

    /**
     * {@inheritdoc}
     * @see FileInterface::save()
     */
    public function save($data): void
    {
        if (is_string($data)) {
            // Make sure that the string is valid data.
            try {
                $this->formatter->decode($data);

View on GitHub (pinned to 6040efed04)

Solutions

  1. Check existence and readability before loading: is_file($path) && is_readable($path); treat 'missing' as empty state and initialize defaults instead of calling load().
  2. Fix ownership/mode of the file for the PHP user (chown/chmod).
  3. Confirm the path is absolute, correctly spelled, and within open_basedir.
  4. If the file was half-written by an earlier crash, restore from backup or delete it so defaults regenerate.

Example fix

// before
$data = $dataFile->load(); // RuntimeException: Bad Data

// after
$path = $dataFile->getFilePath();
$data = (is_file($path) && is_readable($path)) ? $dataFile->load() : $defaults;
Defensive patterns

Strategy: validation

Validate before calling

$path = $dataFile->getFilePath();
if (!is_file($path) || !is_readable($path)) {
    // load() would throw 'Bad Data'; treat as empty state and use defaults
    return $defaults;
}

Try / catch

try {
    $data = $dataFile->load();
} catch (\RuntimeException $e) {
    // message contains path + 'Bad Data': file missing/unreadable
    $data = $defaults;
}

Prevention

When it happens

Trigger: DataFile::load() on a file that does not exist yet (first run before save, deleted data), is not readable by the PHP user (wrong ownership/mode), or sits outside open_basedir.

Common situations: Plugins reading user/data files before ever creating them; files created by a root CLI run so the web user cannot read; migrations copying files without preserving modes; shared hosting with path restrictions.

Related errors


AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17). Data as JSON: /api/errors/d991eb4d14e8283a. Report an issue: GitHub.