getgrav/grav · error · RuntimeException
Bad collection class: %s
Error message
Bad collection class: %s
What it means
FlexDirectory::createCollection() (line 595) builds collections using the class from the blueprint key data.collection (default GenericCollection), verifying with is_a(..., FlexCollectionInterface::class, true) first. If the configured name is misspelled, not autoloaded, or does not implement the interface, it throws 'Bad collection class'. Like the object check, a non-existent class string fails is_a() and produces the same message.
Source
Thrown at system/src/Grav/Framework/Flex/FlexDirectory.php:595
if (!is_a($className, FlexObjectInterface::class, true)) {
throw new \RuntimeException('Bad object class: ' . $className);
}
return new $className($data, $key, $this, $validate);
}
/**
* @param array $entries
* @param string|null $keyField
* @return FlexCollectionInterface
* @phpstan-return FlexCollectionInterface<FlexObjectInterface>
*/
public function createCollection(array $entries, ?string $keyField = null): FlexCollectionInterface
{
/** phpstan-var class-string $className */
$className = $this->collectionClassName ?: $this->getCollectionClass();
if (!is_a($className, FlexCollectionInterface::class, true)) {
throw new \RuntimeException('Bad collection class: ' . $className);
}
return $className::createFromArray($entries, $this, $keyField);
}
/**
* @param array $entries
* @param string|null $keyField
* @return FlexIndexInterface
* @phpstan-return FlexIndexInterface<FlexObjectInterface>
*/
public function createIndex(array $entries, ?string $keyField = null): FlexIndexInterface
{
/** @phpstan-var class-string $className */
$className = $this->indexClassName ?: $this->getIndexClass();
if (!is_a($className, FlexIndexInterface::class, true)) {
throw new \RuntimeException('Bad index class: ' . $className);
}View on GitHub (pinned to 6040efed04)
Solutions
- Point data.collection at an autoloaded class implementing Grav\Framework\Flex\Interfaces\FlexCollectionInterface (normally extending Grav\Framework\Flex\FlexCollection).
- Confirm runtime autoloadability (composer dump-autoload; plugin enabled).
- Use single-quoted YAML class names and re-check backslash escaping.
Example fix
# before (blueprint.yaml) data: collection: 'Vendor\Plugin\Flex\ThingsCollection' # class does not exist / wrong interface # after data: collection: 'Grav\Framework\Flex\GenericCollection'
Defensive patterns
Strategy: validation
Validate before calling
$class = $directory->getConfig('data.collection', \Grav\Framework\Flex\GenericCollection::class);
if (!class_exists($class) || !is_a($class, \Grav\Framework\Flex\Interfaces\FlexCollectionInterface::class, true)) {
// fix blueprint before calling getCollection()/createCollection()
} Type guard
function isValidFlexCollectionClass(string $class): bool
{
return class_exists($class)
&& \is_a($class, \Grav\Framework\Flex\Interfaces\FlexCollectionInterface::class, true);
} Try / catch
try {
$collection = $directory->createCollection($entries);
} catch (\RuntimeException $e) {
if (str_starts_with($e->getMessage(), 'Bad collection class')) {
// configuration defect: log the class name and stop
}
} Prevention
- Assert custom collection classes extend FlexCollection during plugin boot.
- Keep blueprint class names in sync with plugin refactors.
- Clear config cache after changing flex blueprint settings.
When it happens
Trigger: A custom flex type whose data.collection entry names a class that is not a FlexCollection implementation; renaming a collection class without updating the blueprint; YAML escaping errors doubling backslashes; the providing plugin being disabled so its autoloader no longer resolves the class.
Common situations: Custom flex types with specialized collection classes; plugin refactors; blueprint overrides in user:// config that stale-copy an old class name.
Related errors
- Bad object class: %s
- Bad index class: %s
- Bad storage class: %s
- Unknown extension type
- Bad Data Formatter
AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17).
Data as JSON: /api/errors/4c37dbcff47a13f1.
Report an issue: GitHub.