go-redis/redis · error

failed to create operation duration histogram

Error message

failed to create operation duration histogram: %w

What it means

Returned by createRecorder (redisotel.go:194) when dbconv.NewClientOperationDuration fails to create the 'db.client.operation.duration' Float64Histogram. Only checked when the MetricGroupCommand group is enabled. The wrapped error comes from the OTel SDK's meter.Float64Histogram call.

Solutions

  1. Search for other code registering 'db.client.operation.duration' and reconcile unit/description metadata
  2. Verify the MeterProvider is from a compatible OTel SDK version
  3. Check that cfg.BucketsOperationDuration contains valid float64 boundary values when HistogramAggregation is ExplicitBucket

Example fix

// before - conflicting 'db.client.operation.duration' from another lib
hist, _ := meter.Float64Histogram("db.client.operation.duration",
    metric.WithUnit("ms")) // conflicts with semconv unit "s"

// after - use the same unit as redisotel semconv (seconds)
hist, _ := meter.Float64Histogram("db.client.operation.duration",
    metric.WithUnit("s"))
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate bucket boundaries are monotonically increasing before Init
for i := 1; i < len(cfg.BucketsOperationDuration); i++ {
    if cfg.BucketsOperationDuration[i] <= cfg.BucketsOperationDuration[i-1] {
        return fmt.Errorf("invalid bucket boundaries")
    }
}

Try / catch

if err := obs.Init(cfg); err != nil {
    if strings.Contains(err.Error(), "operation duration histogram") {
        log.Error("conflict on 'db.client.operation.duration'; reconcile metadata across OTel integrations")
    }
}

Prevention

When it happens

Trigger: Calling Init with MetricGroups including MetricGroupFlagCommand, and the OTel SDK rejects the histogram creation (duplicate name with conflicting metadata, invalid name, or a broken MeterProvider).

Common situations: Another instrumentation library already registered 'db.client.operation.duration' with different unit or description; the global MeterProvider is the default no-op but an incompatible SDK version is mixed in; custom bucket boundaries in cfg.BucketsOperationDuration are malformed.

Related errors


AI-assisted analysis of go-redis/redis@36d97525cd (2026-08-06). Data as JSON: /api/errors/3883771275bd25f7. Report an issue: GitHub.

Appendix: source

Thrown at extra/redisotel-native/redisotel.go:194

	}
}

// createRecorder creates a metricsRecorder with all instruments based on config.
func (o *ObservabilityInstance) createRecorder(meter metric.Meter, cfg config) (*metricsRecorder, error) {
	var err error

	var operationDuration metric.Float64Histogram
	if cfg.isMetricGroupEnabled(MetricGroupCommand) {
		var operationDurationOpts []metric.Float64HistogramOption
		if cfg.histAggregation == HistogramAggregationExplicitBucket {
			operationDurationOpts = append(operationDurationOpts,
				metric.WithExplicitBucketBoundaries(cfg.bucketsOperationDuration...),
			)
		}
		var operationDurationConv dbconv.ClientOperationDuration
		operationDurationConv, err = dbconv.NewClientOperationDuration(meter, operationDurationOpts...)
		if err != nil {
			return nil, fmt.Errorf("failed to create operation duration histogram: %w", err)
		}
		operationDuration = operationDurationConv.Inst()
	}

	var connectionCount metric.Int64UpDownCounter // OTel semconv: UpDownCounter
	var connectionCreateTime metric.Float64Histogram
	var connectionRelaxedTimeout metric.Int64UpDownCounter
	var connectionHandoff metric.Int64Counter

	if cfg.isMetricGroupEnabled(MetricGroupConnectionBasic) {
		connectionCount, err = meter.Int64UpDownCounter(
			dbconv.ClientConnectionCount{}.Name(),
			metric.WithDescription(dbconv.ClientConnectionCount{}.Description()),
			metric.WithUnit(dbconv.ClientConnectionCount{}.Unit()),
		)
		if err != nil {
			return nil, fmt.Errorf("failed to create connection count metric: %w", err)
		}

View on GitHub (pinned to 36d97525cd)