{"record":{"id":"323c5f29812fcee3","repo":"dotnet/machinelearning","slug":"metric-typeof-tmetrics-not-implemented","errorCode":null,"errorMessage":"Metric {typeof(TMetrics)} not implemented","messagePattern":"Metric (.+?) not implemented","errorType":"exception","errorClass":"NotImplementedException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.ML.AutoML/Experiment/Runners/CrossValSummaryRunner.cs","lineNumber":157,"sourceCode":"                    l2: GetAverageOfNonNaNScores(newMetrics.Select(x => x.MeanSquaredError)),\n                    rms: GetAverageOfNonNaNScores(newMetrics.Select(x => x.RootMeanSquaredError)),\n                    lossFunction: GetAverageOfNonNaNScores(newMetrics.Select(x => x.LossFunction)),\n                    rSquared: GetAverageOfNonNaNScores(newMetrics.Select(x => x.RSquared)));\n                return result as TMetrics;\n            }\n\n            if (typeof(TMetrics) == typeof(RankingMetrics))\n            {\n                var newMetrics = metrics.Select(x => x as RankingMetrics);\n                Contracts.Assert(newMetrics != null);\n\n                var result = new RankingMetrics(\n                    dcg: GetAverageOfNonNaNScoresInNestedEnumerable(newMetrics.Select(x => x.DiscountedCumulativeGains)),\n                    ndcg: GetAverageOfNonNaNScoresInNestedEnumerable(newMetrics.Select(x => x.NormalizedDiscountedCumulativeGains)));\n                return result as TMetrics;\n            }\n\n            throw new NotImplementedException($\"Metric {typeof(TMetrics)} not implemented\");\n        }\n\n        private static double[] GetAverageOfNonNaNScoresInNestedEnumerable(IEnumerable<IEnumerable<double>> results)\n        {\n            if (results.All(result => result == null))\n            {\n                // If all nested enumerables are null, we say the average is a null enumerable as well.\n                // This is expected to happen on Multiclass metrics where the TopKAccuracyForAllK\n                // array can be null if the topKPredictionCount isn't a valid number.\n                // In that case all of the \"results\" enumerables will be null anyway, and so\n                // returning null is the expected solution.\n                return null;\n            }\n\n            // In case there are only some null elements, we'll ignore them:\n            results = results.Where(result => result != null);\n\n            double[] arr = new double[results.ElementAt(0).Count()];","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/dotnet/machinelearning/blob/7b76e69cf964daeca3f1377af6bc5543284d56c6/src/Microsoft.ML.AutoML/Experiment/Runners/CrossValSummaryRunner.cs#L139-L175","documentation":"GetAverageMetrics averages per-fold TMetrics across cross-validation runs but only implements aggregation for a fixed set of metric types (binary/classification/regression/ranking). Requesting any other TMetrics type falls through to NotImplementedException.","triggerScenarios":"Running cross-validation experiments with a TMetrics type not covered by the type-switch (e.g. a custom IMetrics implementation or an unsupported metrics class) so the final `throw new NotImplementedException` is reached.","commonSituations":"Using a newer or custom metrics type with CrossValSummaryRunner after adding a new task/metric family without extending the runner.","solutions":["Use one of the supported TMetrics types (BinaryClassificationMetrics, MulticlassClassificationMetrics, RegressionMetrics, RankingMetrics).","Update the library / use a task-specific experiment class whose metrics the runner supports.","If implementing a new metrics type, add an aggregation branch in GetAverageMetrics."],"exampleFix":"// before\nvar exp = mlContext.Auto().CreateExperiment().SetCrossValSummaryRunner<MyCustomMetrics>(...);\n// after\nvar exp = mlContext.Auto().CreateExperiment().SetCrossValSummaryRunner<RegressionMetrics>(...);","handlingStrategy":"type-guard","validationCode":"if (!typeof(IMetrics).IsAssignableFrom(typeof(TMetrics)) || typeof(TMetrics) == typeof(IMetrics))\n    throw new NotSupportedException($\"{typeof(TMetrics)} aggregation unsupported\");","typeGuard":"bool IsSupportedMetrics<T>() => typeof(T) == typeof(BinaryClassificationMetrics) || typeof(T) == typeof(MulticlassClassificationMetrics) || typeof(T) == typeof(RegressionMetrics) || typeof(T) == typeof(RankingMetrics);","tryCatchPattern":"try { avg = runner.GetAverageMetrics(); }\ncatch (NotImplementedException ex) { logger.LogError(ex, \"Unsupported metric aggregation for {Type}\", typeof(TMetrics)); }","preventionTips":["Only use documented TMetrics types with CrossValSummaryRunner","Extend GetAverageMetrics when adding custom metrics","Test cross-val experiments with the exact metric type at startup"],"tags":["csharp","metrics","not-implemented"],"backgroundTag":"method-not-implemented","analyzedSha":"7b76e69cf964daeca3f1377af6bc5543284d56c6","analyzedAt":"2026-09-11T12:35:38.930Z","contentChangedAt":"2026-09-11T12:35:38.930Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}