octobercms/october · error · SystemException

backend::lang.widget.not_registered

backend::lang.widget.not_registered

Error message

A widget class name ':name' has not been registered

What it means

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.

Source

Thrown at modules/dashboard/widgets/dash/HasReportWidgets.php:48

    }

    /**
     * makeDashReportWidget object from a dash report object
     */
    protected function makeDashReportWidget(DashReport $report)
    {
        if (isset($this->reportWidgets[$report->reportName])) {
            return $this->reportWidgets[$report->reportName];
        }

        // Create dash widget instance
        $widgetProps = $report->config;
        $widgetProps['alias'] = $this->alias . studly_case($this->nameToId($report->reportName));

        $widgetClass = $widgetProps['widget'] ?? ($widgetProps['widgetClass'] ?? null);
        $widgetClass = $this->dashManager->resolveReportWidget($widgetClass);
        if (!class_exists($widgetClass)) {
            throw new SystemException(Lang::get(
                'backend::lang.widget.not_registered',
                ['name' => $widgetClass]
            ));
        }

        $widget = new $widgetClass($this->controller, $report, $widgetProps);

        return $this->reportWidgets[$report->reportName] = $widget;
    }

    /**
     * isReportWidget checks if a report type is a widget or not
     */
    protected function isReportWidget(string $reportType): bool
    {
        if (!$reportType) {
            return false;
        }

View on GitHub (pinned to b608633a7e)

Solutions

  1. Correct the widget reference in the definition to the exact registered class name (or its registered code).
  2. Register the widget in the provider plugin's registerReportWidgets() if it is new.
  3. Verify the class is autoloadable: class_exists('MyPlugin\ReportWidgets\Sales') in tinker; run composer dump-autoload if not.
  4. List registered widget codes/resolved classes via DashManager to compare what resolveReportWidget returns for your value.

Example fix

# before (dashboard definition)
reports:
  sales:
    widget: MyPlugn\ReportWidgets\Sales

# after
reports:
  sales:
    widget: MyPlugin\ReportWidgets\SalesWidget
Defensive patterns

Strategy: type-guard

Validate before calling

$widgetClass = $widgetManager->resolveReportWidget($config['widget'] ?? null);
if (!class_exists($widgetClass)) {
    throw new \ValidationException(['widget' => "Widget class {$widgetClass} does not exist"]);
}

Type guard

/** True when the widget reference resolves to a loadable class. */
function resolvesToWidgetClass(?string $ref): bool
{
    if ($ref === null) {
        return false;
    }
    $class = \Dashboard\Classes\DashManager::instance()->resolveReportWidget($ref);

    return class_exists($class);
}

Try / catch

try {
    $widget = $this->makeDashReportWidget($report);
} catch (\SystemException $e) {
    // definition references a missing widget: skip that report and keep the dashboard usable
    \Log::warning('Skipping report '.$report->reportName.': '.$e->getMessage());
    continue;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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