octobercms/october · error · SystemException
Invalid order rule type
Error message
Invalid order rule type
What it means
ReportQueryBuilder::applyOrderRule() maps the order rule's data attribute type to an ORDER BY column: dimension, metric (resolved via findMetricByCodeStrict) or dimension_field. Any other value from the order rule's getDataAttributeType() hits default and throws SystemException('Invalid order rule type'). Order rules arrive from dashboard/widget definitions or request payloads, so this is almost always malformed or stale sorting configuration rather than a code bug in the builder.
Source
Thrown at modules/dashboard/classes/ReportQueryBuilder.php:966
*
* @param QueryBuilder $query
*/
protected function applyOrderRule(QueryBuilder $query): void
{
$columnName = match ($this->orderRule->getDataAttributeType()) {
ReportDataOrderRule::ATTR_TYPE_DIMENSION =>
($this->dimension->isDate() && $this->groupInterval !== ReportDataSourceBase::GROUP_INTERVAL_FULL)
? $this->dimension->getDataSetColumName()
: ($this->dimension->getLabelColumnName() ?? $this->dimension->getDatabaseColumnName()),
ReportDataOrderRule::ATTR_TYPE_METRIC =>
ReportMetric::findMetricByCodeStrict($this->metrics, $this->orderRule->getAttributeName())
->getDataSetColumName(),
ReportDataOrderRule::ATTR_TYPE_DIMENSION_FIELD =>
$this->dimension->findDimensionFieldByCode($this->orderRule->getAttributeName())->getCode(),
default => throw new SystemException('Invalid order rule type')
};
$query->orderBy(
$this->evalDbObjectName($columnName),
$this->orderRule->isAscending() ? 'asc' : 'desc'
);
}
/**
* evalDbObjectName validates and trims a database object name
*
* @param string $name
* @return string
*/
protected function evalDbObjectName(string $name): string
{
return trim($name);
}View on GitHub (pinned to b608633a7e)
Solutions
- Set the order rule type to one of ReportDataOrderRule::ATTR_TYPE_DIMENSION / ATTR_TYPE_METRIC / ATTR_TYPE_DIMENSION_FIELD when constructing the rule.
- Validate sort payloads at the controller boundary and reject unknown types with a 422-style response instead of letting them reach the builder.
- Update or reset saved dashboard definitions after upgrading so order rules use the current format.
- When ordering by a metric, also verify the metric code exists on the data source (unknown codes throw 'Unknown metric' from the same code path).
Example fix
// before
$orderRule = new ReportDataOrderRule;
$orderRule->setAttributeName('status'); // type never set
// after
$orderRule = new ReportDataOrderRule;
$orderRule->setDataAttributeType(ReportDataOrderRule::ATTR_TYPE_DIMENSION);
$orderRule->setAttributeName('status');
$orderRule->setIsAscending(true); Defensive patterns
Strategy: validation
Validate before calling
$validOrderTypes = [
ReportDataOrderRule::ATTR_TYPE_DIMENSION,
ReportDataOrderRule::ATTR_TYPE_METRIC,
ReportDataOrderRule::ATTR_TYPE_DIMENSION_FIELD,
];
$order = $payload['orderBy'] ?? null;
if ($order !== null) {
$type = $order['attribute']['type'] ?? null;
if (!in_array($type, $validOrderTypes, true)) {
throw new InvalidArgumentException('Invalid order rule attribute type.');
}
// if ordering by metric, also confirm the code exists
if ($type === ReportDataOrderRule::ATTR_TYPE_METRIC) {
ReportMetric::findMetricByCodeStrict($metrics, $order['attribute']['name'], false)
?? throw new InvalidArgumentException('Unknown metric in order rule.');
}
} Type guard
function isValidOrderRuleType(mixed $type): bool
{
return is_string($type) && in_array($type, [
ReportDataOrderRule::ATTR_TYPE_DIMENSION,
ReportDataOrderRule::ATTR_TYPE_METRIC,
ReportDataOrderRule::ATTR_TYPE_DIMENSION_FIELD,
], true);
} Prevention
- Construct order rules with the ATTR_TYPE_* constants only.
- Validate sort payloads before they reach the query builder.
- Reset saved dashboard definitions when the order-rule payload schema changes.
When it happens
Trigger: A report data request sends orderBy/orderByDimension payload where the attribute type is missing, empty or invented ('attr', 'column'); composing a ReportDataOrderRule manually without setting the type; old saved dashboard definition using a pre-rename type value.
Common situations: Front-end builds its own sort payload instead of using the widget's helper; API consumers guessing the schema; dashboard definitions persisted before an upgrade where the order-rule format changed.
Related errors
- Invalid aggregate function:
- Invalid filter attribute type
- Invalid filter operation:
- Table name is required.
- Dimension is required.
AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21).
Data as JSON: /api/errors/fe11a329acbf2fb7.
Report an issue: GitHub.