octobercms/october · error · SystemException
Widget class [{$widgetClass}] not registered.
Error message
Widget class [{$widgetClass}] not registered. What it means
After a widgetClass is provided to Dash::onRunCustomWidgetHandler, DashManager::getVueReportWidget looks it up in the registered Vue report widget list. That list only contains report widgets registered through the plugin system that are subclasses of Dashboard\Classes\VueReportWidgetBase. An unknown class returns null and this SystemException is thrown.
Source
Thrown at modules/dashboard/widgets/Dash.php:617
}
/**
* onRunCustomWidgetHandler handler
*/
public function onRunCustomWidgetHandler()
{
$handlerName = post('handler');
$widgetConfig = post('widget_config');
$extraData = post('extra_data', []);
$widgetClass = $widgetConfig['widgetClass'];
if (!$widgetClass) {
throw new SystemException("Custom widget class [{$widgetClass}] is not set.");
}
$widget = DashManager::instance()->getVueReportWidget($widgetClass, $this->controller);
if (!$widget) {
throw new SystemException("Widget class [{$widgetClass}] not registered.");
}
$result = $widget->runHandler(
$widgetConfig,
$handlerName,
$extraData
);
return $result;
}
/**
* makeDataSource
*/
protected function makeDataSource(string $dataSourceClass): ReportDataSourceBase
{
$dataSourceManager = DashManager::instance();
$dataSource = $dataSourceManager->getDataSource($dataSourceClass);View on GitHub (pinned to b608633a7e)
Solutions
- Register the widget in the owning plugin: public function registerReportWidgets() { return ['MyPlugin\ReportWidgets\Sales' => ['label' => 'Sales']]; }
- Make the widget class extend Dashboard\Classes\VueReportWidgetBase (not ReportWidgetBase) so DashManager::listVueReportWidgets includes it.
- Confirm the exact fully qualified class name in the payload matches the registered key (case-sensitive, no leading backslash mismatch).
- Ensure the plugin is enabled; clear cache and re-run composer dump-autoload if the class file exists but is not autoloadable.
Example fix
// before
class SalesWidget extends \Backend\Classes\ReportWidgetBase {}
// after
class SalesWidget extends \Dashboard\Classes\VueReportWidgetBase {}
// Plugin.php
public function registerReportWidgets()
{
return ['MyPlugin\ReportWidgets\SalesWidget' => ['label' => 'Sales']];
} Defensive patterns
Strategy: validation
Validate before calling
$manager = \Dashboard\Classes\DashManager::instance();
if (!in_array($widgetClass, $manager->listVueReportWidgetClasses(), true)) {
throw new \ValidationException(['widgetClass' => "{$widgetClass} is not a registered Vue report widget"]);
} Type guard
/** True when the class is registered AND extends VueReportWidgetBase. */
function isRegisteredVueWidget(string $class): bool
{
return in_array($class, \Dashboard\Classes\DashManager::instance()
->listVueReportWidgetClasses(), true);
} Try / catch
try {
$widget = DashManager::instance()->getVueReportWidget($class, $this->controller);
} catch (\SystemException $e) {
\Log::error('Vue widget lookup failed: '.$e->getMessage());
return ajax()->force(['error' => $e->getMessage()]);
} Prevention
- Register every custom dashboard widget in registerReportWidgets() as part of the plugin checklist.
- Extend VueReportWidgetBase for dashboard widgets; keep ReportWidgetBase for form/widget contexts.
- Add a boot-time sanity assertion in dev envs that every widget referenced in default dashboards is registered.
When it happens
Trigger: POSTing a handler request with widgetClass set to a class that is not registered via the plugin's registerReportWidgets(); registering the widget but extending Backend\Classes\ReportWidgetBase (or ReportWidgetBase) instead of VueReportWidgetBase, which excludes it from the Vue list; plugin providing the widget is disabled; fully qualified class name typo (wrong namespace/case).
Common situations: Building a first custom dashboard widget and forgetting the registration array in Plugin.php; widget works as a CMS report widget but is called through the Vue report path; class moved to another namespace during a refactor; plugin folder renamed so the class name no longer matches.
Related errors
- Widget class [{$widgetClass}] not registered.
- Data source [{$dataSourceClass}] class is not registered.
- Invalid handler name
- Handler does not exist
- The provided class is not a dashboard widget: {$className}
AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21).
Data as JSON: /api/errors/068761f0fcb4316c.
Report an issue: GitHub.