{"record":{"id":"daee15821c7b0f0a","repo":"octobercms/october","slug":"backend-lang-widget-not-registered","errorCode":"backend::lang.widget.not_registered","errorMessage":"A widget class name ':name' has not been registered","messagePattern":"A widget class name ':name' has not been registered","errorType":"exception","errorClass":"SystemException","httpStatus":null,"severity":"error","filePath":"modules/dashboard/widgets/dash/HasReportWidgets.php","lineNumber":48,"sourceCode":"    }\n\n    /**\n     * makeDashReportWidget object from a dash report object\n     */\n    protected function makeDashReportWidget(DashReport $report)\n    {\n        if (isset($this->reportWidgets[$report->reportName])) {\n            return $this->reportWidgets[$report->reportName];\n        }\n\n        // Create dash widget instance\n        $widgetProps = $report->config;\n        $widgetProps['alias'] = $this->alias . studly_case($this->nameToId($report->reportName));\n\n        $widgetClass = $widgetProps['widget'] ?? ($widgetProps['widgetClass'] ?? null);\n        $widgetClass = $this->dashManager->resolveReportWidget($widgetClass);\n        if (!class_exists($widgetClass)) {\n            throw new SystemException(Lang::get(\n                'backend::lang.widget.not_registered',\n                ['name' => $widgetClass]\n            ));\n        }\n\n        $widget = new $widgetClass($this->controller, $report, $widgetProps);\n\n        return $this->reportWidgets[$report->reportName] = $widget;\n    }\n\n    /**\n     * isReportWidget checks if a report type is a widget or not\n     */\n    protected function isReportWidget(string $reportType): bool\n    {\n        if (!$reportType) {\n            return false;\n        }","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/octobercms/october/blob/b608633a7e8922487d91a8161499020121c3b3bf/modules/dashboard/widgets/dash/HasReportWidgets.php#L30-L66","documentation":"HasReportWidgets::makeDashReportWidget instantiates a report widget for a DashReport. It takes the widget class from config keys widget or widgetClass, normalizes it through DashManager::resolveReportWidget (which maps widget codes to class names), then requires class_exists. If resolution does not yield a loadable class, a SystemException with backend::lang.widget.not_registered is thrown.","triggerScenarios":"A dashboard definition entry whose widget key contains a typo or wrong namespace; referencing a widget code (alias) that was never registered in registerReportWidgets(); the plugin providing the widget is uninstalled or its folder casing changed; composer autoload cache stale after moving a widget class.","commonSituations":"Hand-editing a dashboard YAML/JSON definition; moving widgets between plugins during refactoring; environments where a plugin exists in one instance but not another (definition synced via database); widget registered under a code but definition uses the raw class name with a typo.","solutions":["Correct the widget reference in the definition to the exact registered class name (or its registered code).","Register the widget in the provider plugin's registerReportWidgets() if it is new.","Verify the class is autoloadable: class_exists('MyPlugin\\ReportWidgets\\Sales') in tinker; run composer dump-autoload if not.","List registered widget codes/resolved classes via DashManager to compare what resolveReportWidget returns for your value."],"exampleFix":"# before (dashboard definition)\nreports:\n  sales:\n    widget: MyPlugn\\ReportWidgets\\Sales\n\n# after\nreports:\n  sales:\n    widget: MyPlugin\\ReportWidgets\\SalesWidget","handlingStrategy":"type-guard","validationCode":"$widgetClass = $widgetManager->resolveReportWidget($config['widget'] ?? null);\nif (!class_exists($widgetClass)) {\n    throw new \\ValidationException(['widget' => \"Widget class {$widgetClass} does not exist\"]);\n}","typeGuard":"/** True when the widget reference resolves to a loadable class. */\nfunction resolvesToWidgetClass(?string $ref): bool\n{\n    if ($ref === null) {\n        return false;\n    }\n    $class = \\Dashboard\\Classes\\DashManager::instance()->resolveReportWidget($ref);\n\n    return class_exists($class);\n}","tryCatchPattern":"try {\n    $widget = $this->makeDashReportWidget($report);\n} catch (\\SystemException $e) {\n    // definition references a missing widget: skip that report and keep the dashboard usable\n    \\Log::warning('Skipping report '.$report->reportName.': '.$e->getMessage());\n    continue;\n}","preventionTips":["Add an automated check that every widget referenced in default dashboard definitions is registered.","Register widgets by fully qualified class name to avoid code-alias drift.","After renaming a widget class, migrate saved definitions or register the old name as an alias."],"tags":["dashboard","widget-registration","class-not-found","config"],"backgroundTag":"class-not-found","analyzedSha":"b608633a7e8922487d91a8161499020121c3b3bf","analyzedAt":"2026-08-21T04:24:57.515Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}