{"record":{"id":"9fc7aafd8bc39a69","repo":"octobercms/october","slug":"the-provided-class-is-not-a-report-widget","errorCode":null,"errorMessage":"The provided class is not a report widget: ","messagePattern":"The provided class is not a report widget: ","errorType":"exception","errorClass":"SystemException","httpStatus":null,"severity":"error","filePath":"modules/dashboard/classes/StaticReportWidgetContainer.php","lineNumber":50,"sourceCode":"     * Widget classes must extend Backend\\Classes\\ReportWidgetBase.\n     * @param array $widgetConfig Widget properties\n     * @return string Returns the rendered widget string\n     */\n    public function renderWidget(string $widgetClass, array $widgetConfig): string\n    {\n        $widget = $this->makeWidget($widgetClass);\n        $widget->setProperties($widgetConfig);\n\n        return $widget->render();\n    }\n\n    /**\n     * makeWidget\n     */\n    private function makeWidget(string $widgetClass)\n    {\n        if (!is_subclass_of($widgetClass, ReportWidgetBase::class)) {\n            throw new SystemException(\"The provided class is not a report widget: \" . $widgetClass);\n        }\n\n        return new $widgetClass($this->controller);\n    }\n}\n","sourceCodeStart":32,"sourceCodeEnd":56,"githubUrl":"https://github.com/octobercms/october/blob/b608633a7e8922487d91a8161499020121c3b3bf/modules/dashboard/classes/StaticReportWidgetContainer.php#L32-L56","documentation":"StaticReportWidgetContainer::makeWidget() instantiates a widget class from dashboard configuration and guards it with is_subclass_of($widgetClass, ReportWidgetBase::class); anything else throws SystemException('The provided class is not a report widget: <class>'). The class name comes from widget configuration in a dashboard definition, so the error means the configured class either does not exist in that case or is not a ReportWidgetBase subclass (note: is_subclass_of on a non-existent class returns false without autoload success).","triggerScenarios":"A dashboard definition (DB-stored or default) whose static widget entry names a plain class, a controller, or a namespaced class string with a typo; referencing a widget class that moved namespaces between versions; widget class present in a plugin that is disabled or not loaded.","commonSituations":"Plugin disabled/removed but the user's saved dashboard still references its widget; copy-pasting a widget alias without registering it; YAML/JSON dashboard config using the wrong key so a non-class string (e.g. a partial name) is read as the class.","solutions":["Point the widget config at a class that extends Dashboard\\ReportWidgets\\ReportWidgetBase (or the module's ReportWidgetBase), fully namespaced.","Fix typos/namespace changes in the dashboard definition; after renaming a widget class, update saved dashboard records or reset the dashboard to defaults.","Ensure the plugin providing the widget is installed and enabled so the class is autoloadable.","If stale user dashboards are the issue, reset the affected user's dashboard configuration (Dashboard model / user preferences)."],"exampleFix":"// before (dashboard definition)\nwidgets:\n  sales: SalesSummary // not a report widget class / unnamespaced\n\n// after\nwidgets:\n  sales: \\MyPlugin\\ReportWidgets\\SalesSummary","handlingStrategy":"type-guard","validationCode":"$widgetClass = $widgetConfig['class'] ?? null;\nif (!is_string($widgetClass) || !class_exists($widgetClass) || !is_subclass_of($widgetClass, ReportWidgetBase::class)) {\n    throw new ApplicationException(\"Dashboard widget '{$widgetClass}' is not available.\");\n}\n$container->renderWidget($widgetClass, $widgetConfig);","typeGuard":"function isReportWidgetClass(mixed $class): bool\n{\n    return is_string($class) && class_exists($class) && is_subclass_of($class, ReportWidgetBase::class);\n}","tryCatchPattern":"try {\n    return $container->renderWidget($class, $config);\n} catch (SystemException $e) {\n    if (str_contains($e->getMessage(), 'not a report widget')) {\n        Log::warning($e->getMessage());\n        return '<!-- widget unavailable -->'; // graceful placeholder on a dashboard\n    }\n    throw $e;\n}","preventionTips":["Use fully-qualified class names in dashboard definitions and keep them in sync with renames.","Remove references to widgets of uninstalled/disabled plugins, or reset user dashboards to defaults.","Guard widget rendering so one bad entry degrades gracefully instead of failing the whole dashboard."],"tags":["dashboard","widget","class-resolution","config-validation"],"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"}