{"record":{"id":"4141af69a56a4371","repo":"octobercms/october","slug":"widget-class-widgetclass-not-registered-4141af","errorCode":null,"errorMessage":"Widget class [{$widgetClass}] not registered.","messagePattern":"Widget class \\[(.+?)\\] not registered\\.","errorType":"exception","errorClass":"SystemException","httpStatus":null,"severity":"error","filePath":"modules/dashboard/widgets/dash/HasWidgetData.php","lineNumber":87,"sourceCode":"     * onGetWidgetCustomData\n     */\n    public function onGetWidgetCustomData()\n    {\n        $fetchData = new ReportFetchData;\n        $fetchData->fillFromPost();\n\n        $widgetClass = post('widget_config[widgetClass]');\n        if (!$widgetClass) {\n            throw new SystemException(\"Custom widget class [{$widgetClass}] is not set.\");\n        }\n\n        $widget = DashManager::instance()->getVueReportWidget(\n            $widgetClass,\n            $this->controller\n        );\n\n        if (!$widget) {\n            throw new SystemException(\"Widget class [{$widgetClass}] not registered.\");\n        }\n\n        $data = $widget->getData($fetchData);\n\n        return ajax()->force(['data' => $data]);\n    }\n\n    /**\n     * onGetWidgetStaticContent\n     */\n    public function onGetWidgetStaticContent()\n    {\n        $widgetConfig = (array) post('widget_config');\n        $reportName = $widgetConfig['reportName'] ?? null;\n        if (!isset($widgetConfig['type']) || $widgetConfig['type'] !== 'static') {\n            return false;\n        }\n","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/octobercms/october/blob/b608633a7e8922487d91a8161499020121c3b3bf/modules/dashboard/widgets/dash/HasWidgetData.php#L69-L105","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nclass SalesWidget extends \\Backend\\Classes\\ReportWidgetBase {}\n\n// after\nclass SalesWidget extends \\Dashboard\\Classes\\VueReportWidgetBase {}\n// plus registration in Plugin.php::registerReportWidgets()","handlingStrategy":"validation","validationCode":"if (!DashManager::instance()->isVueReportWidget($widgetClass)) {\n    throw new \\ValidationException(['widgetClass' => \"{$widgetClass} is not a registered Vue report widget\"]);\n}","typeGuard":"$ok = \\Dashboard\\Classes\\DashManager::instance()->isVueReportWidget($widgetClass);","tryCatchPattern":"try {\n    $data = $widget->getData($fetchData);\n} catch (\\SystemException $e) {\n    \\Log::error('Widget data fetch failed: '.$e->getMessage());\n    return ajax()->force(['error' => 'Widget unavailable']);\n}","preventionTips":["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."],"tags":["dashboard","widget-registration","vue-report-widget","plugin"],"backgroundTag":"widget-not-registered","analyzedSha":"b608633a7e8922487d91a8161499020121c3b3bf","analyzedAt":"2026-08-21T04:24:57.515Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}