getgrav/grav · error · RuntimeException
__METHOD__(): 'object' should be instance of FlexObjectInter
Error message
__METHOD__(): 'object' should be instance of FlexObjectInterface
What it means
FlexForm::instance() accepts an 'object' option that must implement FlexObjectInterface; anything else (a plain object, an array, a legacy Page) triggers this 400 RuntimeException. The factory delegates form creation to the object itself, so it must be a real Flex object. Use the 'directory'+'key' path instead when you do not have an object instance.
Source
Thrown at system/src/Grav/Framework/Flex/FlexForm.php:76
private $submitMethod;
/**
* @param array $options Options to initialize the form instance:
* (string) name: Form name, allows you to use custom form.
* (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);View on GitHub (pinned to 6040efed04)
Solutions
- Load a proper Flex object first: $object = $grav['flex']->getDirectory('pages')->getObject($key); then pass it.
- If you only know type+key, use FlexForm::instance(['directory' => $directory, 'key' => $key]) instead of 'object'.
- For legacy Page instances, migrate to the Flex page object via the pages flex directory before building the form.
Example fix
// before
$form = FlexForm::instance(['object' => $page]); // $page is legacy PageInterface
// after
$flex = Grav::instance()['flex'];
$object = $flex->getDirectory('pages')->getObject($page->route());
$form = FlexForm::instance(['object' => $object]); Defensive patterns
Strategy: type-guard
Type guard
use Grav\Framework\Flex\Interfaces\FlexObjectInterface;
function isFlexObject(mixed $value): bool
{
return $value instanceof FlexObjectInterface;
} Prevention
- Type-hint parameters against FlexObjectInterface in your own APIs so misuse fails earlier.
- Convert legacy Page objects via the flex pages directory before building forms.
- When in doubt, use the 'directory'+'key' options — they resolve the object for you.
When it happens
Trigger: Passing a legacy Grav Page (PageInterface) or stdClass/array where a FlexObject is expected; passing an object from a different abstraction layer (e.g. a Doctrine entity); passing an uninitialized FlexObjectInterface mock in tests.
Common situations: Porting legacy page code to Flex Pages and reusing $page variables in FlexForm::instance(); plugin code receiving 'object' from a request/JSON payload instead of loading it from the directory.
Related errors
- __METHOD__(): 'directory' should be instance of FlexDirector
- __METHOD__(): You need to pass option 'directory'
- Flash has no directory
- __METHOD__(): You need to pass option 'directory' or 'object
- Flash has no object
AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17).
Data as JSON: /api/errors/73409ad48210cd85.
Report an issue: GitHub.