getgrav/grav · error · RuntimeException

Flash has no object

Error message

Flash has no object

What it means

When a FlexForm initializes and its FlexFormFlash exists, the flash must carry an object: FlexFormFlash::init() rebuilds it from config or from the stored 'object.serialized' data. If the flash JSON has no serialized object (directory-only flash) or the flex type is no longer registered, getObject() returns null and this RuntimeException is thrown. It is a session-state mismatch between the flash and the current form.

Source

Thrown at system/src/Grav/Framework/Flex/FlexForm.php:168

        $this->messages = [];
        $this->submitted = false;
        $this->data = null;
        $this->files = [];
        $this->unsetFlash();

        /** @var FlexFormFlash $flash */
        $flash = $this->getFlash();
        if ($flash->exists()) {
            $data = $flash->getData();
            if (null !== $data) {
                $data = new Data($data, $this->getBlueprint());
                $data->setKeepEmptyValues(true);
                $data->setMissingValuesAsNull(true);
            }

            $object = $flash->getObject();
            if (null === $object) {
                throw new RuntimeException('Flash has no object');
            }

            $this->object = $object;
            $this->data = $data;

            $includeOriginal = (bool)($this->getBlueprint()->form()['images']['original'] ?? null);
            $this->files = $flash->getFilesByFields($includeOriginal);
        }

        return $this;
    }

    /**
     * @param string $uniqueId
     * @return void
     */
    public function setUniqueId(string $uniqueId): void
    {

View on GitHub (pinned to 6040efed04)

Solutions

  1. Delete the stale flash (FormFlash::delete() for the form's uniqueFormId, or clear user session) so the form starts fresh.
  2. Ensure every step that reads the form passes the same 'object'/'directory'+'key' options used when the flash was created.
  3. Verify the flex type is registered in the current codebase before re-opening the form.
  4. On major upgrades, bump the form unique id/name so old flashes are not reused.

Example fix

// before
$form = FlexForm::instance($options)->initialize(); // Flash has no object

// after
use Grav\Framework\Form\FormFlash;
$flash = new FormFlash($uniqueId);
if ($flash->exists() && $flash->getObject() === null) {
    $flash->delete(); // stale/incompatible flash: start over
}
$form = FlexForm::instance($options)->initialize();
Defensive patterns

Strategy: validation

Validate before calling

// Verify the flash carries an object before initializing an object form
$flash = new \Grav\Framework\Flex\FlexFormFlash($uniqueId);
if ($flash->exists() && $flash->getObject() === null) {
    $flash->delete(); // cannot restore object: restart the form
}
$form = FlexForm::instance($options)->initialize();

Try / catch

try {
    $form->initialize();
} catch (\Grav\Framework\Flex\Exception\RuntimeException $e) {
    if (str_contains($e->getMessage(), 'Flash has no object')) {
        $form->getFlash()->delete();
        $form = FlexForm::instance($options)->initialize(); // clean retry
    }
}

Prevention

When it happens

Trigger: A flash created for a directory-level form (stores only directory type) being consumed by an object-level FlexForm with the same unique id; the flex type renamed/removed between form submission and re-render; flash file from an older Grav schema without the object.serialized block; createObject() failing silently during restore (e.g. storage key collision).

Common situations: Multi-step forms where step 1 initializes the flash without an object but step 2 expects one; deploys changing flex type names while admin sessions held open forms; local dev against production session data.

Related errors


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