getgrav/grav · error · RuntimeException

__METHOD__(): 'directory' should be instance of FlexDirector

Error message

__METHOD__(): 'directory' should be instance of FlexDirectory

What it means

In FlexForm::instance(), when no 'object' is given the 'directory' option must be a FlexDirectory instance; passing the flex type string, an array of options, or any other value throws this 400 RuntimeException. The directory is used to look up or create the object by key, so a raw string cannot work here.

Source

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

     *                          (string) unique_id: Unique id for this form instance.
     *                          (array) form: Custom form fields.
     *                          (FlexObjectInterface) object: Object instance.
     *                          (string) key: Object key, used only if object instance isn't given.
     *                          (FlexDirectory) directory: Flex Directory, mandatory if object isn't given.
     *
     * @return FlexFormInterface
     */
    public static function instance(array $options = [])
    {
        if (isset($options['object'])) {
            $object = $options['object'];
            if (!$object instanceof FlexObjectInterface) {
                throw new RuntimeException(__METHOD__ . "(): 'object' should be instance of FlexObjectInterface", 400);
            }
        } elseif (isset($options['directory'])) {
            $directory = $options['directory'];
            if (!$directory instanceof FlexDirectory) {
                throw new RuntimeException(__METHOD__ . "(): 'directory' should be instance of FlexDirectory", 400);
            }
            $key = $options['key'] ?? '';
            $object = $directory->getObject($key) ?? $directory->createObject([], $key);
        } else {
            throw new RuntimeException(__METHOD__ . "(): You need to pass option 'directory' or 'object'", 400);
        }

        $name = $options['name'] ?? '';

        // There is no reason to pass object and directory.
        unset($options['object'], $options['directory']);

        return $object->getForm($name, $options);
    }

    /**
     * FlexForm constructor.
     * @param string $name

View on GitHub (pinned to 6040efed04)

Solutions

  1. Resolve the string to a FlexDirectory first: $directory = $grav['flex']->getDirectory('pages'); then pass ['directory' => $directory, 'key' => $key].
  2. Check getDirectory() did not return null for unregistered types before calling instance().
  3. If you already have the object, pass 'object' instead and drop 'directory'.

Example fix

// before
$form = FlexForm::instance(['directory' => 'pages', 'key' => '/about']);

// after
$flex = Grav::instance()['flex'];
$form = FlexForm::instance([
    'directory' => $flex->getDirectory('pages'),
    'key' => '/about',
]);
Defensive patterns

Strategy: type-guard

Type guard

use Grav\Framework\Flex\FlexDirectory;

function isFlexDirectory(mixed $value): bool
{
    return $value instanceof FlexDirectory;
}

Prevention

When it happens

Trigger: FlexForm::instance(['directory' => 'pages', 'key' => '/blog']) passing the type name; passing a blueprint array or directory configuration array; passing a FlexIndex or collection object instead of the directory.

Common situations: First-time flex form integrations where authors assume the type string is accepted; refactoring from $grav['flex']->getDirectory() inline calls to options arrays and forgetting the resolution step.

Related errors


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