octobercms/october · error · SystemException
The provided class is not a report data source:
Error message
The provided class is not a report data source:
What it means
HasDataSources::getDataSource(string $className) only instantiates classes that were previously registered in the manager's $dataSources array; the method then double-checks is_subclass_of($className, ReportDataSourceBase::class) and throws SystemException('The provided class is not a report data source: <class>') if the registered entry is not a ReportDataSourceBase subclass. Because registration happens via registerDataSource, this fires when a plugin registered a non-data-source class (or the class changed parent) — not when the class is merely unknown (unknown returns null).
Source
Thrown at modules/dashboard/classes/dashmanager/HasDataSources.php:46
$this->dataSources[$className] = [
'displayName' => $displayName
];
}
/**
* getDataSource returns a data source instance by its class name.
* @throws SystemException if the provided class name is not a subclass Dashboard\Classes\ReportDataSourceBase.
* @param string $className A data source class name.
* @return ?ReportDataSourceBase Returns the data source instance or null.
*/
public function getDataSource(string $className): ?ReportDataSourceBase
{
if (!array_key_exists($className, $this->dataSources)) {
return null;
}
if (!is_subclass_of($className, ReportDataSourceBase::class)) {
throw new SystemException("The provided class is not a report data source: " . $className);
}
return new $className();
}
/**
* listDataSourceClasses returns class and display names of registered data sources.
* @return array
*/
public function listDataSourceClasses(): array
{
$result = [];
foreach ($this->dataSources as $className => $info) {
$result[$className] = $info['displayName'];
}
return $result;
}
View on GitHub (pinned to b608633a7e)
Solutions
- Make the registered class extend Dashboard\Classes\ReportDataSourceBase and implement its abstract members (defineColumns/defineMetrics etc.).
- Fix the class string passed to registerDataSource() to reference the intended, existing data source class.
- Only register data sources at plugin boot (Plugin::boot / registerDashboards) and remove stray registrations of helpers or models.
- Check parent class changes after upgrading the dashboard module and restore the correct base class.
Example fix
// before
$manager->registerDataSource(\MyPlugin\Classes\OrderHelper::class);
$manager->getDataSource(\MyPlugin\Classes\OrderHelper::class); // throws
// after
class OrdersDataSource extends \Dashboard\Classes\ReportDataSourceBase { /* ... */ }
$manager->registerDataSource(OrdersDataSource::class); Defensive patterns
Strategy: type-guard
Validate before calling
if (!class_exists($className) || !is_subclass_of($className, ReportDataSourceBase::class)) {
throw new InvalidArgumentException("{$className} is not a report data source.");
}
$source = $manager->getDataSource($className); Type guard
function isReportDataSourceClass(mixed $class): bool
{
return is_string($class) && class_exists($class) && is_subclass_of($class, ReportDataSourceBase::class);
} Try / catch
try {
$source = $manager->getDataSource($className);
} catch (SystemException $e) {
Log::error($e->getMessage());
// skip misregistered source, continue with remaining dashboards
$source = null;
} Prevention
- Register data sources only in plugin boot code, referencing classes that extend ReportDataSourceBase.
- Re-check parent classes after upgrading the dashboard module.
- Add a boot-time assertion (once per environment) that all registered data sources pass is_subclass_of.
When it happens
Trigger: Calling DashManager's registerDataSource with a plain class, an interface name, or a class that extends something else, then getDataSource($thatClass); refactoring a data source to no longer extend ReportDataSourceBase while leaving it registered; registering a string that resolves to a trait or abstract helper.
Common situations: Plugin boot code copy-pasted with the wrong class name into registerDataSource(); inheritance changed during an upgrade (class now extends a different base); typo in the namespace making is_subclass_of fail.
Related errors
- The provided class is not a dashboard widget: {$className}
- The provided class is not a report widget:
- Trying to get selected row without a popup reference.
- Key property ${keyProperty} is not found in the Inspector da
- Key property (${keyProperty}) value should be a string. Prop
AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21).
Data as JSON: /api/errors/39afcaac427eaf4f.
Report an issue: GitHub.