thanos-io/thanos · error

cannot convert exponential to native histogram. Scale must…

Error message

cannot convert exponential to native histogram. Scale must be >= -4, was %d

What it means

exponentialToNativeHistogram maps OTLP exponential histograms to Prometheus native histograms, which only support scale >= -4. If the data point's scale is below -4 the conversion cannot proceed and this error is returned (the whole metric fails; a smaller scale would need bucket regeneration).

Solutions

  1. Increase the histogram scale on the producer (e.g. rescale in the SDK/collector so scale >= -4)
  2. Configure the OTel collector's transform/aggregate processor to convert scale before forwarding
  3. Disable native-histogram conversion for these metrics so they are exported differently
  4. Prefer scaleDown path only when scale > 8; for scale < -4 you must fix the source data

Example fix

// before: producer sets very coarse scale
agg := aggregator.NewExponential(aggConfig{Scale: -6})
// after: ensure minimum supported scale
agg := aggregator.NewExponential(aggConfig{Scale: -4})
Defensive patterns

Strategy: validation

Validate before calling

if dp.Scale() < -4 {
    return fmt.Errorf("histogram scale %d below native-histogram minimum -4", dp.Scale())
}

Type guard

func nativeHistCompatible(dp pmetric.ExponentialHistogramDataPoint) bool {
    return dp.Scale() >= -4
}

Try / catch

h, annots, err := exponentialToNativeHistogram(dp)
if err != nil {
    if strings.Contains(err.Error(), "Scale must be >= -4") {
        log.Warnf("dropping histogram: %v", err)
        return nil
    }
    return err
}

Prevention

When it happens

Trigger: Receiving OTLP ExponentialHistogram data points with Scale() < -4 — very coarse bucket layouts — sent to the OTLP translation endpoint and converted with native histogram support enabled.

Common situations: Producers configured with extremely low-resolution exponential histograms; SDKs letting users set negative scale aggressively; metric data crafted/synthetic with scale like -7.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07). Data as JSON: /api/errors/25f058833bef4bfc. Report an issue: GitHub.

Appendix: source

Thrown at pkg/receive/otlptranslator/histograms.go:76

		exemplars, err := getPromExemplars[pmetric.ExponentialHistogramDataPoint](ctx, &c.everyN, pt)
		if err != nil {
			return annots, err
		}
		ts.Exemplars = append(ts.Exemplars, exemplars...)
	}

	return annots, nil
}

// exponentialToNativeHistogram translates an OTel Exponential Histogram data point
// to a Prometheus Native Histogram.
func exponentialToNativeHistogram(p pmetric.ExponentialHistogramDataPoint) (prompb.Histogram, annotations.Annotations, error) {
	var annots annotations.Annotations
	scale := p.Scale()
	if scale < -4 {
		return prompb.Histogram{}, annots,
			fmt.Errorf("cannot convert exponential to native histogram."+
				" Scale must be >= -4, was %d", scale)
	}

	var scaleDown int32
	if scale > 8 {
		scaleDown = scale - 8
		scale = 8
	}

	pSpans, pDeltas := convertBucketsLayout(p.Positive(), scaleDown)
	nSpans, nDeltas := convertBucketsLayout(p.Negative(), scaleDown)

	h := prompb.Histogram{
		// The counter reset detection must be compatible with Prometheus to
		// safely set ResetHint to NO. This is not ensured currently.
		// Sending a sample that triggers counter reset but with ResetHint==NO
		// would lead to Prometheus panic as it does not double check the hint.
		// Thus we're explicitly saying UNKNOWN here, which is always safe.

View on GitHub (pinned to 35b8b99117)