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

  1. Register the widget class under registerReportWidgets() in its plugin.
  2. Extend Dashboard\Classes\VueReportWidgetBase so DashManager treats it as a Vue report widget.
  3. Match the class string in the payload exactly with the registered key.
  4. 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

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


AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21). Data as JSON: /api/errors/4141af69a56a4371. Report an issue: GitHub.