{"record":{"id":"67379d1a864ee3d6","repo":"getgrav/grav","slug":"bad-object-class-s","errorCode":null,"errorMessage":"Bad object class: %s","messagePattern":"Bad object class: (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"system/src/Grav/Framework/Flex/FlexDirectory.php","lineNumber":578,"sourceCode":"        if (null === $this->storage) {\n            $this->storage = $this->createStorage();\n        }\n\n        return $this->storage;\n    }\n\n    /**\n     * @param array $data\n     * @param string $key\n     * @param bool $validate\n     * @return FlexObjectInterface\n     */\n    public function createObject(array $data, string $key = '', bool $validate = false): FlexObjectInterface\n    {\n        /** @phpstan-var class-string $className */\n        $className = $this->objectClassName ?: $this->getObjectClass();\n        if (!is_a($className, FlexObjectInterface::class, true)) {\n            throw new \\RuntimeException('Bad object class: ' . $className);\n        }\n\n        return new $className($data, $key, $this, $validate);\n    }\n\n    /**\n     * @param array $entries\n     * @param string|null $keyField\n     * @return FlexCollectionInterface\n     * @phpstan-return FlexCollectionInterface<FlexObjectInterface>\n     */\n    public function createCollection(array $entries, ?string $keyField = null): FlexCollectionInterface\n    {\n        /** phpstan-var class-string $className */\n        $className = $this->collectionClassName ?: $this->getCollectionClass();\n        if (!is_a($className, FlexCollectionInterface::class, true)) {\n            throw new \\RuntimeException('Bad collection class: ' . $className);\n        }","sourceCodeStart":560,"sourceCodeEnd":596,"githubUrl":"https://github.com/getgrav/grav/blob/6040efed04efa69b8209448ed81308e7c24147c2/system/src/Grav/Framework/Flex/FlexDirectory.php#L560-L596","documentation":"FlexDirectory::createObject() (line 578) instantiates the directory's object class, configured via the flex type blueprint key data.object (default GenericObject). Before constructing, is_a($className, FlexObjectInterface::class, true) verifies the class implements that interface; a typo'd, missing, or non-Flex class string throws 'Bad object class'. Note is_a() on a class string that does not exist also returns false, so a non-autoloadable name produces the same error.","triggerScenarios":"A custom flex type whose blueprint sets data.object to a misspelled class, a class in a non-autoloaded namespace, a plain data class not extending FlexObject, or a YAML quoting mistake that doubles the backslashes; loading any object from such a directory.","commonSituations":"First setup of a custom flex type in a plugin; moving/renaming plugin classes without updating the blueprint; disabling the plugin that provided the class while its blueprint remains cached.","solutions":["Point data.object at an autoloaded class implementing Grav\\Framework\\Flex\\Interfaces\\FlexObjectInterface — in practice, one extending Grav\\Framework\\Flex\\FlexObject.","Verify the class loads at runtime: composer dump-autoload and confirm the owning plugin is enabled, since a non-existent class triggers the same error.","In YAML use single-quoted namespace notation ('Vendor\\Plugin\\Flex\\Thing') and check for doubled backslashes."],"exampleFix":"# before (blueprint.yaml)\ndata:\n  object: Vendor/Plugin/Flex/Thing   # wrong separators — not a class name\n\n# after\ndata:\n  object: 'Vendor\\Plugin\\Flex\\ThingObject'","handlingStrategy":"validation","validationCode":"$class = $directory->getConfig('data.object', \\Grav\\Framework\\Flex\\GenericObject::class);\nif (!class_exists($class) || !is_a($class, \\Grav\\Framework\\Flex\\Interfaces\\FlexObjectInterface::class, true)) {\n    // fix blueprint before using the directory\n}","typeGuard":"function isValidFlexObjectClass(string $class): bool\n{\n    return class_exists($class)\n        && \\is_a($class, \\Grav\\Framework\\Flex\\Interfaces\\FlexObjectInterface::class, true);\n}","tryCatchPattern":"try {\n    $object = $directory->createObject($data, $key);\n} catch (\\RuntimeException $e) {\n    if (str_starts_with($e->getMessage(), 'Bad object class')) {\n        // configuration defect: log the class name and fail loudly\n    }\n}","preventionTips":["Add a boot-time assertion for custom flex types verifying data.object implements the interface.","Run composer dump-autoload after moving plugin classes.","Review YAML quoting of namespaced class names in blueprints."],"tags":["flex","configuration","class-loading","blueprint","custom-types"],"backgroundTag":"invalid-object-class-config","analyzedSha":"6040efed04efa69b8209448ed81308e7c24147c2","analyzedAt":"2026-08-17T05:07:31.593Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}