{"record":{"id":"b281de3bbc9f87f4","repo":"microsoft/aspire","slug":"histogram-data-point-has-bucket-counts-without-any-explicit","errorCode":null,"errorMessage":"Histogram data point has bucket counts without any explicit bounds.","messagePattern":"Histogram data point has bucket counts without any explicit bounds\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Dashboard/Otlp/Model/OtlpHelpers.cs","lineNumber":68,"sourceCode":"            Metric.DataOneofCase.Gauge => metric.Gauge.DataPoints.Count,\n            Metric.DataOneofCase.Sum => metric.Sum.DataPoints.Count,\n            Metric.DataOneofCase.Histogram => metric.Histogram.DataPoints.Count,\n            Metric.DataOneofCase.Summary => metric.Summary.DataPoints.Count,\n            Metric.DataOneofCase.ExponentialHistogram => metric.ExponentialHistogram.DataPoints.Count,\n            _ => 0,\n        };\n    }\n\n    internal static void ValidateHistogramDataPoint(HistogramDataPoint point)\n    {\n        if (!double.IsFinite(point.Sum))\n        {\n            throw new InvalidOperationException(\"Histogram data point sum must be finite.\");\n        }\n\n        if (point.BucketCounts.Count > 0 && point.ExplicitBounds.Count == 0)\n        {\n            throw new InvalidOperationException(\"Histogram data point has bucket counts without any explicit bounds.\");\n        }\n    }\n\n    internal static void ValidateNumberDataPoint(NumberDataPoint point)\n    {\n        if (point.ValueCase == NumberDataPoint.ValueOneofCase.AsDouble && !double.IsFinite(point.AsDouble))\n        {\n            throw new InvalidOperationException(\"Metric data point value must be finite.\");\n        }\n    }\n\n    public static ResourceKey GetResourceKey(this Resource resource)\n    {\n        string? serviceName = null;\n        string? serviceInstanceId = null;\n        string? processExecutableName = null;\n\n        for (var i = 0; i < resource.Attributes.Count; i++)","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Dashboard/Otlp/Model/OtlpHelpers.cs#L50-L86","documentation":"Aspire Dashboard validates incoming OTLP histogram data points. A histogram that reports bucket counts must also declare the explicit bounds that define those buckets; otherwise the bucket boundaries are unknowable and the data cannot be rendered as a histogram. The library throws this InvalidOperationException during data-point validation to reject malformed/inconsistent histogram telemetry before it is stored.","triggerScenarios":"ValidateHistogramDataPoint is called while importing an OTLP ExportMetricsServiceRequest; it throws when point.BucketCounts.Count > 0 while point.ExplicitBounds.Count == 0. In practice: an SDK or collector forwards histogram metrics with bucket_counts populated but explicit_bounds omitted in the HistogramDataPoint protobuf.","commonSituations":"Hand-rolled OTLP exporters or test harnesses that construct HistogramDataPoint manually and fill bucket_counts without bounds; metric-producing libraries with broken/legacy histogram emission; protobuf messages built by third-party tools that misencode the histogram fields.","solutions":["Fix the telemetry producer so every HistogramDataPoint with bucket_counts also carries a matching explicit_bounds list (bounds.Count should equal bucketCounts.Count - 1 per OTLP spec).","Check the emitting SDK/collector configuration and upgrade to a version that populates explicit bounds for explicit-bucket histograms.","If the data source is out of your control, intercept it upstream (e.g. a collector transform/filter processor) to drop or repair such histogram points before they reach the Dashboard."],"exampleFix":"// before: manual HistogramDataPoint without bounds\nvar point = new HistogramDataPoint { BucketCounts = { 1, 2, 3 } };\n// after: bounds must define every bucket boundary (n-1 boundaries for n buckets)\nvar point = new HistogramDataPoint\n{\n    BucketCounts = { 1, 2, 3 },\n    ExplicitBounds = { 10.0, 100.0 }\n};","handlingStrategy":"validation","validationCode":"// before sending/accepting a histogram data point\nbool valid = point.BucketCounts.Count == 0 || point.ExplicitBounds.Count > 0;","typeGuard":null,"tryCatchPattern":"try\n{\n    repository.AddMetrics(request);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"bucket counts without any explicit bounds\"))\n{\n    logger.LogWarning(ex, \"Dropping histogram data point with buckets but no explicit bounds.\");\n}","preventionTips":["Always populate ExplicitBounds when populating BucketCounts (bounds.Count == bucketCounts.Count - 1).","Use a maintained OpenTelemetry SDK rather than hand-building HistogramDataPoint protobufs.","Add a unit test asserting exporter output histograms include bounds."],"tags":["opentelemetry","metrics","histogram","validation","otlp"],"backgroundTag":"schema-validation-failed","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}