octobercms/october · error · SystemException

The provided class is not a dashboard widget: {$className}

Error message

The provided class is not a dashboard widget: {$className}

What it means

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.

Source

Thrown at modules/dashboard/classes/dashmanager/HasVueReportWidgets.php:80

    /**
     * getWidget returns a dashboard widget instance by its class name.
     * @throws SystemException if the provided class name is not a subclass Dashboard\Classes\VueReportWidgetBase.
     * @param string $className A dashboard widget class name.
     * @param Controller $controller Parent controller instance.
     * @return ?VueReportWidgetBase Returns the dashboard widget instance or null.
     */
    public function getVueReportWidget(string $className, Controller $controller): ?VueReportWidgetBase
    {
        if ($this->vueReportWidgets === null) {
            $this->listVueReportWidgets();
        }

        if (!array_key_exists($className, $this->vueReportWidgets)) {
            return null;
        }

        if (!is_subclass_of($className, VueReportWidgetBase::class)) {
            throw new SystemException("The provided class is not a dashboard widget: {$className}");
        }

        return new $className($controller);
    }
}

View on GitHub (pinned to b608633a7e)

Solutions

  1. Register only classes extending Dashboard\Classes\VueReportWidgetBase and request those by their exact class name.
  2. If the widget is a classic (non-Vue) report widget, serve it through StaticReportWidgetContainer / the classic path instead of getVueReportWidget.
  3. After renaming a widget class, update both the registration call and any dashboard definitions storing the class string.
  4. Clear the cached widget list (listVueReportWidgets populates the registry) after fixing registrations, e.g. by clearing the plugin/config cache.

Example fix

// before
$manager->registerVueReportWidget(\MyPlugin\Widgets\ClassicWidget::class); // extends ReportWidgetBase

// after
class SalesChart extends \Dashboard\Classes\VueReportWidgetBase { /* ... */ }
$manager->registerVueReportWidget(SalesChart::class);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!class_exists($className) || !is_subclass_of($className, VueReportWidgetBase::class)) {
    throw new InvalidArgumentException("{$className} is not a Vue report widget.");
}
$widget = $manager->getVueReportWidget($className, $controller);

Type guard

function isVueReportWidgetClass(mixed $class): bool
{
    return is_string($class) && class_exists($class) && is_subclass_of($class, VueReportWidgetBase::class);
}

Try / catch

try {
    $widget = $manager->getVueReportWidget($className, $controller);
} catch (SystemException $e) {
    if (str_contains($e->getMessage(), 'not a dashboard widget')) {
        return null; // skip this widget, render the rest of the dashboard
    }
    throw $e;
}

Prevention

When it happens

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

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

Related errors


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