{"record":{"id":"726a427e7743df57","repo":"octobercms/october","slug":"the-dimension-metric-is-already-registered","errorCode":null,"errorMessage":"The dimension metric is already registered: ","messagePattern":"The dimension metric is already registered: ","errorType":"exception","errorClass":"SystemException","httpStatus":null,"severity":"error","filePath":"modules/dashboard/classes/ReportDimension.php","lineNumber":232,"sourceCode":"    public function getYearGroupingField(): ?string\n    {\n        return $this->yearGroupingField;\n    }\n\n    /**\n     * Registers a dimension metric.\n     * @param ReportMetric $metric A metric to add.\n     * @return ReportDimension Returns the dimension object for chaining.\n     */\n    public function addDimensionMetric(ReportMetric $metric): ReportDimension\n    {\n        $knownMetric = array_filter(\n            $this->metrics,\n            fn ($item) => $item->getCode() === $metric->getCode()\n        );\n\n        if (count($knownMetric)) {\n            throw new SystemException('The dimension metric is already registered: ' . $metric->getCode());\n        }\n\n        $this->metrics[] = $metric;\n        return $this;\n    }\n\n    /**\n     * A shorthand version of addDimensionMetric.\n     * Adds a calculated metric that doesn't work with the database.\n     * @param string $displayName Metric display name for the UI.\n     * @return ReportDimension Returns the dimension object for chaining.\n     */\n    public function addCalculatedMetric(string $metricCode, string $displayName): ReportDimension\n    {\n        return $this->addDimensionMetric(new ReportMetric(\n            $metricCode,\n            $metricCode,\n            $displayName,","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/octobercms/october/blob/b608633a7e8922487d91a8161499020121c3b3bf/modules/dashboard/classes/ReportDimension.php#L214-L250","documentation":"Dimension metrics are keyed by their code — that code is what widget configurations and fetch requests reference. addDimensionMetric() filters the already-registered metrics by code and throws a SystemException when a metric with the same code is registered twice on the same dimension.","triggerScenarios":"Calling $dimension->addDimensionMetric(new ReportMetric('total', ...)) twice, or looping over a config array that contains two ReportMetric definitions with $code = 'total' for the same dimension.","commonSituations":"Copy-pasted metric definitions with the code not updated; merging metric lists from multiple plugins/traits that both define common codes like 'total' or 'count'; dynamic metric generation that re-runs during a request (e.g. re-registration in a loop or on retry).","solutions":["Make each metric code unique on the dimension — rename the duplicate (e.g. 'total' vs 'refunded_total')","Deduplicate the source list by code before registering: array_reduce/array_filter keeping first occurrence","If merging lists from multiple sources, key the merged array by metric code so later entries overwrite rather than duplicate"],"exampleFix":"// before\n$dimension->addDimensionMetric(new ReportMetric('total', 'oc_amount', 'Total', 'sum'));\n$dimension->addDimensionMetric(new ReportMetric('total', 'oc_tax', 'Tax', 'sum'));\n\n// after\n$dimension->addDimensionMetric(new ReportMetric('total', 'oc_amount', 'Total', 'sum'));\n$dimension->addDimensionMetric(new ReportMetric('tax', 'oc_tax', 'Tax', 'sum'));","handlingStrategy":"validation","validationCode":"$registered = [];\nforeach ($metrics as $metric) {\n    if (in_array($metric->getCode(), $registered, true)) {\n        continue; // or log a warning about the duplicate\n    }\n    $dimension->addDimensionMetric($metric);\n    $registered[] = $metric->getCode();\n}","typeGuard":null,"tryCatchPattern":"try {\n    $dimension->addDimensionMetric($metric);\n} catch (SystemException $e) {\n    // duplicate code — log and continue registering the rest\n    Log::warning('Skipped duplicate dimension metric: ' . $metric->getCode());\n}","preventionTips":["Key metric definition arrays by code so duplicates overwrite instead of stacking","Treat metric codes as a public API: renaming breaks dashboards, so choose them once","Run a de-duplication pass over merged metric lists from multiple plugins"],"tags":["php","dashboard","report","dimension","metric","duplicate"],"backgroundTag":"duplicate-registration","analyzedSha":"b608633a7e8922487d91a8161499020121c3b3bf","analyzedAt":"2026-08-21T04:24:57.515Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}