octobercms/october · error · SystemException
Widget class [{$widgetClass}] not registered.
Error message
Widget class [{$widgetClass}] not registered. What it means
In onGetWidgetCustomData, once widgetClass is supplied, DashManager::getVueReportWidget must find it among registered Vue report widgets (registered report widgets that extend VueReportWidgetBase). Null means the class is not in that registry, and this SystemException aborts the data fetch.
Source
Thrown at modules/dashboard/widgets/dash/HasWidgetData.php:87
* onGetWidgetCustomData
*/
public function onGetWidgetCustomData()
{
$fetchData = new ReportFetchData;
$fetchData->fillFromPost();
$widgetClass = post('widget_config[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.");
}
$data = $widget->getData($fetchData);
return ajax()->force(['data' => $data]);
}
/**
* onGetWidgetStaticContent
*/
public function onGetWidgetStaticContent()
{
$widgetConfig = (array) post('widget_config');
$reportName = $widgetConfig['reportName'] ?? null;
if (!isset($widgetConfig['type']) || $widgetConfig['type'] !== 'static') {
return false;
}
View on GitHub (pinned to b608633a7e)
Solutions
- Register the widget class under registerReportWidgets() in its plugin.
- Extend Dashboard\Classes\VueReportWidgetBase so DashManager treats it as a Vue report widget.
- Match the class string in the payload exactly with the registered key.
- Verify with DashManager::instance()->listVueReportWidgetClasses() that the class is expected to resolve.
Example fix
// before
class SalesWidget extends \Backend\Classes\ReportWidgetBase {}
// after
class SalesWidget extends \Dashboard\Classes\VueReportWidgetBase {}
// plus registration in Plugin.php::registerReportWidgets() Defensive patterns
Strategy: validation
Validate before calling
if (!DashManager::instance()->isVueReportWidget($widgetClass)) {
throw new \ValidationException(['widgetClass' => "{$widgetClass} is not a registered Vue report widget"]);
} Type guard
$ok = \Dashboard\Classes\DashManager::instance()->isVueReportWidget($widgetClass);
Try / catch
try {
$data = $widget->getData($fetchData);
} catch (\SystemException $e) {
\Log::error('Widget data fetch failed: '.$e->getMessage());
return ajax()->force(['error' => 'Widget unavailable']);
} Prevention
- Check isVueReportWidget() before calling data endpoints for custom widgets.
- Keep a single registration point for all report widgets in the plugin.
- Test data endpoints for every shipped widget in CI.
When it happens
Trigger: widgetClass names a class not registered via registerReportWidgets(); the class is registered but extends ReportWidgetBase instead of VueReportWidgetBase so it is filtered out of listVueReportWidgets; disabled plugin; namespace or case mismatch between payload and registered key.
Common situations: New custom widget where registration was skipped; converting a legacy report widget to the dashboard without changing its base class; deployment where the widget plugin is inactive; stale widget definitions in the database referencing removed classes.
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/4141af69a56a4371.
Report an issue: GitHub.