octobercms/october · error · SystemException
Table name is required.
Error message
Table name is required.
What it means
ReportQueryBuilder::validate() runs before query construction and throws SystemException('Table name is required.') when the $tableName property is empty. The builder renders GROUP BY / aggregate SQL directly against this table name, so building a query without one is a programming/configuration error, not a data condition. The property is normally set via the builder's fluent table()/dataSource setup before buildQuery() is invoked.
Source
Thrown at modules/dashboard/classes/ReportQueryBuilder.php:661
$result[$metric->getCode()] = $row->{$columnName};
}
return $result;
}
//
// Internal Query Building
//
/**
* validate ensures required properties are set
*
* @throws SystemException
*/
protected function validate(): void
{
if (!$this->tableName) {
throw new SystemException('Table name is required.');
}
if (!$this->dimension) {
throw new SystemException('Dimension is required.');
}
if (($this->dateStart || $this->dateEnd) && $this->startTimestamp !== null) {
throw new SystemException('Cannot use both date range and timestamp filtering.');
}
if (!$this->dateStart && $this->startTimestamp === null) {
throw new SystemException('Either date range or start timestamp is required.');
}
if ($this->limit !== null && $this->pagination !== null) {
throw new SystemException('Cannot use both limit and pagination.');
}
}View on GitHub (pinned to b608633a7e)
Solutions
- Set the table before building: $builder->table('orders') (or ensure the data source definition provides the table name) so $tableName is non-empty when validate() runs.
- If you subclass ReportQueryBuilder, check you did not reset $tableName to '' or null in the subclass.
- Verify the data source's definition/tableName resolution logic returns a real table (log/dd the value just before build).
- Confirm the table exists in the database; if a migration renamed it, update the data source to the new name.
Example fix
// before
$builder = new ReportQueryBuilder;
$builder->setDimension($dim)->applyMetrics($metrics);
$data = $builder->buildQuery()->get();
// after
$builder = new ReportQueryBuilder;
$builder->table('orders')->setDimension($dim)->applyMetrics($metrics);
$data = $builder->buildQuery()->get(); Defensive patterns
Strategy: validation
Validate before calling
if (!strlen((string) $dataSource->getTableName())) {
throw new InvalidArgumentException('Data source must define a table before querying.');
}
$builder->table($dataSource->getTableName()); Prevention
- Configure the builder fully (table, dimension, time filter) before triggering build; keep setup in one method.
- Assert required properties in a single pre-build checklist in your own wrapper around ReportQueryBuilder.
- Cover each data source with an integration test that builds one query — this catches missing table definitions early.
When it happens
Trigger: Creating a ReportQueryBuilder (or subclass) and calling a method that triggers buildQuery()/applySelect() without first setting the table — e.g. forgetting $builder->table('orders') or building from a data source whose tableName/columns definition returns an empty string; subclass overriding the property default with ''.
Common situations: Custom report data source that forgets to declare its table in the definition array; refactoring a builder setup method and dropping the table() call; database table renamed in a migration but the data source definition still points at nothing/empty.
Related errors
- Dimension is required.
- Cannot find the requested row group.
- Inspector container ${$containerHolder.data['inspector-conta
- Cannot switch to container: a container element is not found
- Inspector surface unique ID should be defined.
AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21).
Data as JSON: /api/errors/6bb9c6bb09092583.
Report an issue: GitHub.