octobercms/october · error · SystemException
Cannot use both date range and timestamp filtering.
Error message
Cannot use both date range and timestamp filtering.
What it means
ReportQueryBuilder::validate() forbids mixing the two supported time-filtering modes: an explicit date range (dateStart/dateEnd on a date column) and timestamp-based filtering (startTimestamp). Setting any of dateStart/dateEnd together with a non-null startTimestamp throws SystemException('Cannot use both date range and timestamp filtering.'). The builder generates different WHERE clauses for each mode, so the combination is ambiguous and rejected rather than guessed.
Source
Thrown at modules/dashboard/classes/ReportQueryBuilder.php:669
//
/**
* 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.');
}
}
/**
* buildQuery constructs the query builder
*
* @param bool $skipGrouping
* @param bool $skipPagination
* @param array $forceMetrics
* @return QueryBuilderView on GitHub (pinned to b608633a7e)
Solutions
- Choose one mode: keep setDateStart/setDateEnd for date-column filtering and drop setStartTimestamp, or vice versa.
- When merging request/config input, explicitly null out the other mode: if timestamp provided, clear dateStart/dateEnd before building.
- If both arrive from the UI, add precedence logic (e.g. timestamp wins) that clears the losing pair before validate() runs.
- Check cloned/reused builder instances — reset startTimestamp (or dates) between builds.
Example fix
// before
$builder->setDateRange('2026-01-01', '2026-02-01')->setStartTimestamp(1767225600);
// after
$builder->setDateRange('2026-01-01', '2026-02-01');
// or, timestamp mode only:
// $builder->setStartTimestamp(1767225600); Defensive patterns
Strategy: validation
Validate before calling
// Enforce one time-filter mode before configuring the builder
if ($request->filled('start_timestamp')) {
$builder->setStartTimestamp((int) $request->input('start_timestamp'));
} else {
$builder->setDateRange($request->input('date_start'), $request->input('date_end'));
} Prevention
- Never call both setDateRange/setDateStart/setDateEnd and setStartTimestamp on one builder instance.
- When merging saved widget properties with request input, clear the losing time-filter mode explicitly.
- Reset builder state (or use fresh instances) when building multiple queries in a loop.
When it happens
Trigger: Calling both $builder->setDateRange($start, $end) (or setDateStart/setDateEnd) and $builder->setStartTimestamp($ts) on the same builder before it validates; a widget config that carries both a human 'range' preset (converted to dates) and an explicit timestamp, with merging code that keeps both.
Common situations: Dashboard UI sends a saved preset range plus a manually typed timestamp after a config merge; refactoring from timestamp filtering to date ranges while the old property is still set in a base class or cloned builder; copy-pasting setup code from another builder instance.
Related errors
- Either date range or start timestamp is required.
- Cannot use both limit and pagination.
- Table name is required.
- Dimension is required.
- Invalid aggregate function:
AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21).
Data as JSON: /api/errors/8e4d57b05d079e34.
Report an issue: GitHub.