{"record":{"id":"f428e9c081820a24","repo":"octobercms/october","slug":"the-aggregate-function-cannot-be-empty","errorCode":null,"errorMessage":"The aggregate function cannot be empty.","messagePattern":"The aggregate function cannot be empty\\.","errorType":"exception","errorClass":"SystemException","httpStatus":null,"severity":"error","filePath":"modules/dashboard/classes/ReportMetric.php","lineNumber":78,"sourceCode":"    {\n        if (!strlen($code)) {\n            throw new SystemException('The metric code cannot be empty.');\n        }\n\n        if (!preg_match('/^[a-z][a-z0-9_]+$/i', $code)) {\n            throw new SystemException('The metric code can only contain Latin letters, numbers and underscore. The first character must be a letter');\n        }\n\n        if (!strlen($databaseColumnName)) {\n            throw new SystemException('The database column name cannot be empty.');\n        }\n\n        if (!strlen($displayName)) {\n            throw new SystemException('The display name cannot be empty.');\n        }\n\n        if (!strlen($aggregateFunction)) {\n            throw new SystemException('The aggregate function cannot be empty.');\n        }\n\n        $knownAggregateFunctions = [\n            self::AGGREGATE_SUM,\n            self::AGGREGATE_AVG,\n            self::AGGREGATE_MIN,\n            self::AGGREGATE_MAX,\n            self::AGGREGATE_COUNT,\n            self::AGGREGATE_NONE,\n            self::AGGREGATE_COUNT_DISTINCT,\n            self::AGGREGATE_COUNT_DISTINCT_NOT_NULL\n        ];\n\n        if (!in_array($aggregateFunction, $knownAggregateFunctions)) {\n            throw new SystemException('The aggregate function is not supported: ' . $aggregateFunction);\n        }\n\n        $this->code = $code;","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/octobercms/october/blob/b608633a7e8922487d91a8161499020121c3b3bf/modules/dashboard/classes/ReportMetric.php#L60-L96","documentation":"ReportMetric's constructor rejects an empty $aggregateFunction string with SystemException. The aggregate function decides how the metric is computed in SQL (sum/avg/min/max/count/none/count_distinct/count_distinct_not_null) and is later matched against a whitelist, so an empty value has no meaning. This guard fires before the whitelist check, catching the case where the argument was simply not provided. Use the AGGREGATE_* constants rather than raw strings.","triggerScenarios":"Calling `new ReportMetric('code', 'col', 'Label', '')` — most often the 4th argument is omitted in a variadic/array-driven construction, or a config read like $cfg['aggregate'] ?? '' yields '' instead of a valid constant.","commonSituations":"Config-driven metric definitions missing the 'aggregate' key; developers assuming count is the default; passing null (typed string coerces or errors) or an uninitialized variable.","solutions":["Pass one of the ReportMetric::AGGREGATE_* constants as the 4th argument, e.g. ReportMetric::AGGREGATE_SUM.","Default the config key sensibly: $fn = $cfg['aggregate'] ?? ReportMetric::AGGREGATE_COUNT; before constructing.","For raw precomputed values, use AGGREGATE_NONE instead of an empty string.","Re-run after the fix; the follow-up whitelist error ('The aggregate function is not supported') confirms you are now passing a non-empty but unrecognized value."],"exampleFix":"// before\nnew ReportMetric('revenue', 'amount', 'Revenue', '');\n\n// after\nnew ReportMetric('revenue', 'amount', 'Revenue', ReportMetric::AGGREGATE_SUM);","handlingStrategy":"validation","validationCode":"$allowed = [\n    ReportMetric::AGGREGATE_SUM, ReportMetric::AGGREGATE_AVG,\n    ReportMetric::AGGREGATE_MIN, ReportMetric::AGGREGATE_MAX,\n    ReportMetric::AGGREGATE_COUNT, ReportMetric::AGGREGATE_NONE,\n    ReportMetric::AGGREGATE_COUNT_DISTINCT, ReportMetric::AGGREGATE_COUNT_DISTINCT_NOT_NULL,\n];\n$fn = $config['aggregate'] ?? ReportMetric::AGGREGATE_COUNT;\nif (!in_array($fn, $allowed, true)) {\n    throw new InvalidArgumentException(\"Unsupported aggregate: {$fn}\");\n}\n$metric = new ReportMetric($code, $column, $label, $fn);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass ReportMetric::AGGREGATE_* constants instead of hand-typed strings.","Default config-driven aggregate values explicitly (e.g. ?? AGGREGATE_COUNT) instead of letting them become empty strings.","Never build the function string by concatenation; pick from a fixed map."],"tags":["dashboard","report-metric","constructor-validation","aggregate-functions"],"backgroundTag":"constructor-argument-validation","analyzedSha":"b608633a7e8922487d91a8161499020121c3b3bf","analyzedAt":"2026-08-21T04:24:57.515Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}