{"record":{"id":"afd2d48445c7f938","repo":"octobercms/october","slug":"the-provided-class-is-not-a-dashboard-widget-cl","errorCode":null,"errorMessage":"The provided class is not a dashboard widget: {$className}","messagePattern":"The provided class is not a dashboard widget: (.+?)","errorType":"exception","errorClass":"SystemException","httpStatus":null,"severity":"error","filePath":"modules/dashboard/classes/dashmanager/HasVueReportWidgets.php","lineNumber":80,"sourceCode":"    /**\n     * getWidget returns a dashboard widget instance by its class name.\n     * @throws SystemException if the provided class name is not a subclass Dashboard\\Classes\\VueReportWidgetBase.\n     * @param string $className A dashboard widget class name.\n     * @param Controller $controller Parent controller instance.\n     * @return ?VueReportWidgetBase Returns the dashboard widget instance or null.\n     */\n    public function getVueReportWidget(string $className, Controller $controller): ?VueReportWidgetBase\n    {\n        if ($this->vueReportWidgets === null) {\n            $this->listVueReportWidgets();\n        }\n\n        if (!array_key_exists($className, $this->vueReportWidgets)) {\n            return null;\n        }\n\n        if (!is_subclass_of($className, VueReportWidgetBase::class)) {\n            throw new SystemException(\"The provided class is not a dashboard widget: {$className}\");\n        }\n\n        return new $className($controller);\n    }\n}\n","sourceCodeStart":62,"sourceCodeEnd":86,"githubUrl":"https://github.com/octobercms/october/blob/b608633a7e8922487d91a8161499020121c3b3bf/modules/dashboard/classes/dashmanager/HasVueReportWidgets.php#L62-L86","documentation":"HasVueReportWidgets::getVueReportWidget(string $className, Controller $controller) looks the class up among registered Vue report widgets and then verifies is_subclass_of($className, VueReportWidgetBase::class); a registered-but-wrong-type class throws SystemException('The provided class is not a dashboard widget: <class>'). As with data sources, unregistered classes return null — this specific throw means something was registered under that key that does not extend VueReportWidgetBase.","triggerScenarios":"Registering a widget via the manager with a class that extends ReportWidgetBase (the non-Vue base) or a plain class, then requesting it; renaming/re-parenting a widget class after it was registered; two plugins registering the same alias with different classes where the second wins.","commonSituations":"Migrating classic report widgets to Vue widgets and registering the old class by mistake; plugin upgrade changed the base class; copy-paste error in registerVueReportWidget call.","solutions":["Register only classes extending Dashboard\\Classes\\VueReportWidgetBase and request those by their exact class name.","If the widget is a classic (non-Vue) report widget, serve it through StaticReportWidgetContainer / the classic path instead of getVueReportWidget.","After renaming a widget class, update both the registration call and any dashboard definitions storing the class string.","Clear the cached widget list (listVueReportWidgets populates the registry) after fixing registrations, e.g. by clearing the plugin/config cache."],"exampleFix":"// before\n$manager->registerVueReportWidget(\\MyPlugin\\Widgets\\ClassicWidget::class); // extends ReportWidgetBase\n\n// after\nclass SalesChart extends \\Dashboard\\Classes\\VueReportWidgetBase { /* ... */ }\n$manager->registerVueReportWidget(SalesChart::class);","handlingStrategy":"type-guard","validationCode":"if (!class_exists($className) || !is_subclass_of($className, VueReportWidgetBase::class)) {\n    throw new InvalidArgumentException(\"{$className} is not a Vue report widget.\");\n}\n$widget = $manager->getVueReportWidget($className, $controller);","typeGuard":"function isVueReportWidgetClass(mixed $class): bool\n{\n    return is_string($class) && class_exists($class) && is_subclass_of($class, VueReportWidgetBase::class);\n}","tryCatchPattern":"try {\n    $widget = $manager->getVueReportWidget($className, $controller);\n} catch (SystemException $e) {\n    if (str_contains($e->getMessage(), 'not a dashboard widget')) {\n        return null; // skip this widget, render the rest of the dashboard\n    }\n    throw $e;\n}","preventionTips":["Register only VueReportWidgetBase subclasses with registerVueReportWidget; classic widgets go through the classic path.","Keep registration calls and dashboard definitions updated when widget classes move or re-parent.","Guard widget instantiation so a bad registration does not take down the whole dashboard page."],"tags":["dashboard","vue-report-widget","class-resolution","plugin-registration"],"backgroundTag":"class-not-subtype-of-expected-base","analyzedSha":"b608633a7e8922487d91a8161499020121c3b3bf","analyzedAt":"2026-08-21T04:24:57.515Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}