octobercms/october · error · ApplicationException
Dynamic Inspector control options cannot be loaded for the…
Error message
Dynamic Inspector control options cannot be loaded for the specified class.
What it means
onInspectableGetOptions only resolves dynamic options for classes whose hierarchy includes System\Traits\PropertyContainer, verified with class_uses_recursive(). Any other class — even one that exists and autoloads — is rejected, because the handler instantiates the class and calls property APIs that only that trait provides. This is a server-side contract check on the class named by inspectorClassName.
Solutions
- Make the target class use System\Traits\PropertyContainer — directly, or by extending a base like Cms\Classes\ComponentBase that already includes it.
- Double-check the fully-qualified class name posted as inspectorClassName; a wrong-but-existing class fails exactly here.
- After moving or renaming classes, run composer dump-autoload and clear caches.
Example fix
// before
class StockReports
{
}
// after
class StockReports
{
use \System\Traits\PropertyContainer;
}
// or extend a base that already provides the trait
class StockReports extends \Cms\Classes\ComponentBase
{
} Defensive patterns
Strategy: validation
Validate before calling
// Before pointing an inspector at a class, verify the contract server-side
$usable = class_exists($className)
&& in_array(\System\Traits\PropertyContainer::class, class_uses_recursive($className), true);
if (!$usable) {
// choose a class that uses PropertyContainer, e.g. a ComponentBase
} Type guard
function isPropertyContainerClass(string $class): bool
{
return class_exists($class)
&& in_array(\System\Traits\PropertyContainer::class, class_uses_recursive($class), true);
} Prevention
- Only use ComponentBase/WidgetBase-style classes as dynamic-options providers
- Add a boot-time assertion for inspectable classes referenced in inspector configs
- Re-run the class_uses_recursive check in tests after upgrading the CMS
When it happens
Trigger: POST with a valid inspectorProperty and an existing inspectorClassName whose class tree does not include System\Traits\PropertyContainer — for example a plain PHP helper class, a DTO, or a model.
Common situations: Pointing an inspector control's dynamic options at a helper/DTO instead of a component; plugin authors exposing a new inspectable class but forgetting the trait; upgrades that restructured base classes and dropped the trait from the hierarchy.
Related errors
- getDynamicOptionsExtraData must return an object
- Inspector data schema must be an array
- Inspector Object must be an object
- Inspector Parent Object must be an object
- Inspector title is a required string
AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21).
Data as JSON: /api/errors/c3edd89104471f11.
Report an issue: GitHub.
Appendix: source
Thrown at modules/backend/traits/InspectableContainer.php:35
*/
public function onInspectableGetOptions()
{
// Disable asset broadcasting
$this->flushAssets();
$property = trim(post('inspectorProperty'));
if (!$property) {
throw new ApplicationException('The property name is not specified.');
}
$className = trim(post('inspectorClassName'));
if (!$className || $className === 'undefined') {
throw new ApplicationException('The inspectable class name is not specified.');
}
$traitFound = in_array(\System\Traits\PropertyContainer::class, class_uses_recursive($className));
if (!$traitFound) {
throw new ApplicationException('Dynamic Inspector control options cannot be loaded for the specified class.');
}
$obj = new $className(null);
$obj->setProperties(post());
// Nested properties have names like object.property.
// Convert them to Object.Property.
$propertyNameParts = explode('.', $property);
$propertyMethodName = '';
foreach ($propertyNameParts as $part) {
$part = trim($part);
if (!strlen($part)) {
continue;
}
$propertyMethodName .= ucfirst($part);
}View on GitHub (pinned to b608633a7e)