redis/go-redis · error
failed to create operation duration histogram: %w
Error message
failed to create operation duration histogram: %w
What it means
This error is returned from createRecorder in the redisotel-native package when the OpenTelemetry meter fails to create the db.client.operation.duration histogram instrument (via dbconv.NewClientOperationDuration). Init wraps it as 'failed to create metrics recorder' and aborts initialization, so no Redis client metrics are collected. Instrument creation essentially only fails when the MeterProvider is misconfigured, shut down, or a global error handler reports an invalid instrument (bad name/unit/boundaries).
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 c5cad058c7)
Solutions
- Install and set a real metric SDK MeterProvider (e.g. sdkmetric.NewMeterProvider with a Reader) in cfg.MeterProvider, or via otel.SetMeterProvider, before calling Init
- Ensure the MeterProvider has not been Shutdown before Init; re-create the provider if it was
- Check the wrapped error (%w) with errors.Unwrap / otel's global error handler logs to identify the specific instrument-creation failure
- Validate BucketsOperationDuration values (positive, increasing) if using HistogramAggregationExplicitBucket
- Capture the error from Init at startup instead of ignoring it, and fail fast or fall back to disabled metrics
Example fix
// before
err := obs.Init(&redisotel.Config{Enabled: true}) // uses no-op global provider
// after
provider := sdkmetric.NewMeterProvider(sdkmetric.WithReader(sdkmetric.NewPeriodicReader(exp exporter)))
err := obs.Init(&redisotel.Config{Enabled: true, MeterProvider: provider}) Defensive patterns
Strategy: validation
Validate before calling
if cfg.Enabled && cfg.MeterProvider == nil && otel.GetMeterProvider() == noop.NewMeterProvider() {
// no SDK installed; Init will fail or no-op
}
// prefer: pass an explicit sdkmetric.MeterProvider created and not yet Shutdown Type guard
func hasLiveMeterProvider(p metric.MeterProvider) bool { return p != nil } Try / catch
if err := obs.Init(cfg); err != nil {
var root error = errors.Unwrap(err)
otel.Handle(err)
log.Printf("redisotel disabled: %v (root: %v)", err, root)
} Prevention
- Always install an sdkmetric MeterProvider before Init
- Never Shutdown the meter provider before redisotel Init
- Always check the error returned by Init at startup
- Pin consistent go.opentelemetry.io/otel versions across modules
When it happens
Trigger: Calling ObservabilityInstance.Init with a Config that enables MetricGroupFlagCommand while the MeterProvider is nil-and-global-otel is a no-op provider, the provider was already Shutdown(), a custom MeterProvider returns errors for instrument creation, or HistogramAggregationExplicitBucket is set with malformed BucketsOperationDuration.
Common situations: Init is called after otel metric provider shutdown in tests; app forgets to install an SDK MeterProvider so the global no-op provider is used; swapping to a Prometheus or custom reader that rejects the instrument config; upgrading go.opentelemetry.io/otel and hitting semconv/dbconv incompatibilities.
Related errors
- failed to create connection count metric: %w
- failed to create connection handoff metric: %w
- failed to create metrics recorder: %w
- failed to create connection create time histogram: %w
- failed to create connection relaxed timeout metric: %w
AI-assisted analysis of redis/go-redis@c5cad058c7 (2026-09-01).
Data as JSON: /api/errors/d482d54b9a38099e.
Report an issue: GitHub.