{"record":{"id":"f45d11043a5ee151","repo":"thanos-io/thanos","slug":"error-converting-otlp-metrics-to-prometheus-format","errorCode":null,"errorMessage":"error converting OTLP metrics to Prometheus format","messagePattern":"error converting OTLP metrics to Prometheus format","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"pkg/receive/handler_otlp.go","lineNumber":78,"sourceCode":"\n\trequestLimiter := h.Limiter.RequestLimiter()\n\tif r.ContentLength >= 0 {\n\t\tif !requestLimiter.AllowSizeBytes(tenant, r.ContentLength) {\n\t\t\thttp.Error(w, \"write request too large\", http.StatusRequestEntityTooLarge)\n\t\t\treturn\n\t\t}\n\t}\n\n\treq, err := remote.DecodeOTLPWriteRequest(r)\n\tif err != nil {\n\t\tlevel.Error(h.logger).Log(\"msg\", \"Error decoding remote write request\", \"err\", err.Error())\n\t\thttp.Error(w, err.Error(), http.StatusBadRequest)\n\t\treturn\n\t}\n\n\tmetrics, _, err := h.convertToPrometheusFormat(ctx, req.Metrics())\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusBadRequest)\n\t\treturn\n\t}\n\n\ttotalSamples := 0\n\tfor _, ts := range metrics {\n\t\ttotalSamples += len(ts.Samples)\n\t}\n\n\tif !requestLimiter.AllowSeries(tenant, int64(len(metrics))) {\n\t\thttp.Error(w, \"too many timeseries\", http.StatusRequestEntityTooLarge)\n\t\treturn\n\t}\n\n\tif !requestLimiter.AllowSamples(tenant, int64(totalSamples)) {\n\t\thttp.Error(w, \"too many samples\", http.StatusRequestEntityTooLarge)\n\t\treturn\n\t}\n","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/receive/handler_otlp.go#L60-L96","documentation":"HTTP 400 returned when h.convertToPrometheusFormat fails to translate the decoded OTLP metrics into Prometheus time series. The error text is passed straight to the client, so this is usually an issue with the metric data itself (invalid names/labels, out-of-range values, unsupported metric types) rather than transport.","triggerScenarios":"An OTLP ExportMetricsServiceRequest that decodes fine but contains data prometheus's otlp translator rejects: empty/invalid metric or unit names, histogram/exponential-histogram data the converter cannot handle, or a context cancellation/limiter error during conversion.","commonSituations":"Instruments named with characters invalid in Prometheus metric names without normalization; empty metric names from misconfigured SDKs; unsupported metric types sent by newer SDKs to older receive builds.","solutions":["Read the 400 response body; it contains the exact conversion error.","Fix instrument names at the SDK to be valid Prometheus identifiers (use the SDK's name normalization / validation).","Check the SDK isn't emitting metrics with empty names or NaN/invalid values.","Upgrade Thanos/Prometheus to a build supporting the metric types you export (e.g. exponential histograms).","Verify the request context isn't being cancelled upstream (client timeouts mid-flight)."],"exampleFix":"// before: invalid instrument name\nmeter.CreateFloatCounter(\"http.requests!total\")\n// after: valid Prometheus-safe name\nmeter.CreateFloatCounter(\"http_requests_total\")","handlingStrategy":"validation","validationCode":"// validate metric names before export\nfunc validPromName(s string) bool {\n  for _, r := range s {\n    if !(r=='_'||r==':'||(r>='a'&&r<='z')||(r>='A'&&r<='Z')||(r>='0'&&r<='9')) { return false }\n  }\n  return s != \"\"\n}","typeGuard":"func isValidMetric(m Metric) bool { return m != nil && validPromName(m.Name()) }","tryCatchPattern":"if resp.StatusCode == 400 { inspectBody(errText); fixInstrumentNames() }","preventionTips":["Enable SDK metric-name validation early","Keep SDK and Thanos/Prometheus versions current","Integration-test exotic metric types (exponential histograms) before rollout"],"tags":["http","otlp","conversion","thanos"],"backgroundTag":"invalid-argument-value","analyzedSha":"35b8b991177def87ed52dcf10f9b6d87f07282c8","analyzedAt":"2026-09-07T01:49:59.689Z","contentChangedAt":"2026-09-07T01:49:59.689Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}