{"record":{"id":"306a32849ef72c88","repo":"microsoft/aspire","slug":"metric-data-point-has-no-value","errorCode":null,"errorMessage":"Metric data point has no value.","messagePattern":"Metric data point has no value\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/Aspire.Dashboard/Otlp/Storage/SqliteTelemetryRepository.Metrics.Writes.cs","lineNumber":182,"sourceCode":"    }\n\n    private void AddNumberMetricPoint(\n        SqliteConnection connection,\n        IDbTransaction transaction,\n        AddContext context,\n        long instrumentId,\n        NumberDataPoint point,\n        MetricIngestionState ingestionState,\n        MetricPointBatch pointBatch)\n    {\n        try\n        {\n            OtlpHelpers.ValidateNumberDataPoint(point);\n            var pointType = point.ValueCase switch\n            {\n                NumberDataPoint.ValueOneofCase.AsInt => LongPointType,\n                NumberDataPoint.ValueOneofCase.AsDouble => DoublePointType,\n                _ => throw new InvalidOperationException(\"Metric data point has no value.\")\n            };\n            var dimension = GetOrAddMetricDimension(connection, transaction, instrumentId, point.Attributes, ingestionState);\n            var pendingLatest = dimension.PendingPoint;\n            var latest = dimension.LatestPoint;\n            var latestPointType = pendingLatest?.PointType ?? latest?.PointType;\n            var latestEndTimeTicks = pendingLatest?.EndTimeTicks ?? latest?.EndTimeTicks;\n            var sameValue = latestPointType == pointType && (pendingLatest is not null\n                ? pointType == LongPointType ? pendingLatest.IntegerValue == point.AsInt : pendingLatest.DoubleValue == point.AsDouble\n                : pointType == LongPointType ? latest?.IntegerValue == point.AsInt : latest?.DoubleValue == point.AsDouble);\n            var endTimeTicks = OtlpHelpers.UnixNanoSecondsToDateTime(point.TimeUnixNano).Ticks;\n            if (sameValue)\n            {\n                if (pendingLatest is not null)\n                {\n                    pendingLatest.EndTimeTicks = endTimeTicks;\n                    pendingLatest.RepeatCount++;\n                    pendingLatest.SourcePointCount++;\n                    pendingLatest.Exemplars.AddRange(point.Exemplars);","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Dashboard/Otlp/Storage/SqliteTelemetryRepository.Metrics.Writes.cs#L164-L200","documentation":"An OTLP NumberDataPoint must carry a value in either the AsInt or AsDouble oneof case. AddNumberMetricPoint validates the point and throws InvalidOperationException when neither is set, because the repository cannot determine whether to store a long or double value.","triggerScenarios":"AddMetricToDatabase -> AddNumberMetricPoint receives a NumberDataPoint whose ValueCase is neither AsInt nor AsDouble (value oneof unset).","commonSituations":"A custom exporter or hand-built OTLP protobuf omits as_int/as_double; a collector transformation drops the value field; a buggy instrumentation library serializes empty data points.","solutions":["Fix the emitter/exporter to always set either AsInt or AsDouble on number data points.","Check any OTel Collector processors/config that may be stripping point values.","Validate the OTLP payload before export (e.g. with protoc or a validation processor).","If the payload is generated in tests, populate .AsInt or .AsDouble explicitly."],"exampleFix":"// before\nvar point = new NumberDataPoint { TimeUnixNano = now };\n// after\nvar point = new NumberDataPoint { TimeUnixNano = now, AsDouble = 1.0 };","handlingStrategy":"validation","validationCode":"if (point.ValueCase is not (NumberDataPoint.ValueOneofCase.AsInt or NumberDataPoint.ValueOneofCase.AsDouble))\n    throw new InvalidOperationException(\"NumberDataPoint must set AsInt or AsDouble.\");","typeGuard":"static bool HasValue(NumberDataPoint p) =>\n    p.ValueCase is NumberDataPoint.ValueOneofCase.AsInt or NumberDataPoint.ValueOneofCase.AsDouble;","tryCatchPattern":"try\n{\n    await repo.AddMetricsAsync(request);\n}\ncatch (InvalidOperationException ex) when (ex.Message == \"Metric data point has no value.\")\n{\n    logger.LogWarning(ex, \"Dropping malformed number data point.\");\n}","preventionTips":["Always set AsInt or AsDouble on NumberDataPoint when building OTLP payloads.","Add a protobuf payload validation step in custom exporters.","Test exporters against the dashboard ingest path."],"tags":["otlp","metrics","protobuf","ingest"],"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-21T09:17:21.228Z"}