octobercms/october · error · SystemException
Either date range or start timestamp is required.
Error message
Either date range or start timestamp is required.
What it means
ReportQueryBuilder::validate() requires at least one time-filtering mode: either a date range (dateStart set) or a startTimestamp. When neither is present it throws SystemException('Either date range or start timestamp is required.'). The dashboard report queries are intentionally bounded in time (reporting over an unbounded table would scan everything), so the builder refuses to build an unrestricted aggregate query. Note the pairing guard: dateEnd alone is not sufficient — the check keys on dateStart.
Solutions
- Set a bounded window before building: $builder->setDateRange($start, $end) with a non-null start, or $builder->setStartTimestamp($ts).
- If you only have an end date, compute a start (e.g. $end->copy()->subDays(30)) so dateStart is set.
- Apply a sane default period in the widget/controller when the request carries no range, e.g. last 30 days.
- If you genuinely want an unbounded report, pass the earliest possible start timestamp for the table.
Example fix
// before
$builder->table('orders')->setDimension($dim)->applyMetrics($metrics);
$rows = $builder->buildQuery()->get();
// after
$builder->table('orders')->setDimension($dim)->applyMetrics($metrics)
->setStartTimestamp(strtotime('-30 days'));
$rows = $builder->buildQuery()->get(); Defensive patterns
Strategy: validation
Validate before calling
// Guarantee a bounded window before building
$start = $request->input('date_start') ?? now()->subDays(30)->toDateString();
$builder->setDateRange($start, $request->input('date_end'));
// note: dateStart must be set — dateEnd alone is not sufficient Prevention
- Always apply a default reporting period (e.g. last 30 days) in the widget/controller layer.
- Remember dateEnd alone does not satisfy the guard — dateStart or startTimestamp must be present.
- For 'all time' reports, pass the earliest business-plausible start timestamp.
When it happens
Trigger: Building a report query with only table + dimension + metrics, never calling setDateRange()/setDateStart()/setStartTimestamp(); passing dateEnd but not dateStart; a widget whose default period resolution returns null for both values (e.g. empty 'range' param from the UI).
Common situations: New widget that forgets to forward the time range; UI sends 'range=all' or an empty value which the mapping code turns into no filter at all; data source default period not applied because of a config key rename.
Understand the failure class
Background: "Must pass :limit option" / "Missing required option" — required option errors explained — this error's family across 41 libraries.
Related errors
- Cannot use both date range and timestamp filtering.
- Cannot use both limit and pagination.
- Dimension is required.
- Invalid aggregate function:
- Invalid filter attribute type
AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21).
Data as JSON: /api/errors/1f169fad606fc715.
Report an issue: GitHub.
Appendix: source
Thrown at modules/dashboard/classes/ReportQueryBuilder.php:673
*
* @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.');
}
}
/**
* buildQuery constructs the query builder
*
* @param bool $skipGrouping
* @param bool $skipPagination
* @param array $forceMetrics
* @return QueryBuilder
*/
protected function buildQuery(
bool $skipGrouping = false,
bool $skipPagination = false,View on GitHub (pinned to b608633a7e)