go-redis/redis · error

failed to create metrics recorder: %w

Error message

failed to create metrics recorder: %w

What it means

Returned by ObservabilityInstance.Init (redisotel.go:100) when createRecorder fails to build the metricsRecorder. This is the umbrella error wrapping the specific instrument-creation failure that occurred inside createRecorder (one of errors 127-138). It means the entire redisotel-native instrumentation setup failed and no metrics will be collected.

Source

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

	if !cfg.Enabled {
		return nil
	}

	// Get meter provider (use global if not provided)
	meterProvider := cfg.MeterProvider
	if meterProvider == nil {
		meterProvider = otel.GetMeterProvider()
	}

	meter := meterProvider.Meter(
		"github.com/redis/go-redis",
		metric.WithInstrumentationVersion(redis.Version()),
	)

	internalCfg := o.configToInternal(cfg)
	recorder, err := o.createRecorder(meter, internalCfg)
	if err != nil {
		return fmt.Errorf("failed to create metrics recorder: %w", err)
	}

	o.recorder = recorder
	o.initialized = true
	redis.SetOTelRecorder(recorder)

	return nil
}

// IsEnabled returns true if observability is initialized and enabled.
func (o *ObservabilityInstance) IsEnabled() bool {
	o.mu.RLock()
	defer o.mu.RUnlock()
	return o.initialized && o.config != nil && o.config.Enabled
}

// Shutdown cleans up resources and flushes any pending metrics.
// This should be called at application shutdown.

View on GitHub (pinned to 36d97525cd)

Solutions

  1. Inspect the wrapped error via errors.Unwrap to find which specific instrument failed (errors 127-138)
  2. Fix the root cause indicated by the wrapped error (most commonly a duplicate instrument name conflict from another OTel integration)
  3. Ensure the MeterProvider passed via cfg.MeterProvider (or the global provider) is valid and not shut down

Example fix

// before
if err := obs.Init(cfg); err != nil {
    panic(err)
}

// after
if err := obs.Init(cfg); err != nil {
    log.Errorf("redisotel init failed: %v", err)
    if unwrapped := errors.Unwrap(err); unwrapped != nil {
        log.Errorf("root cause: %v", unwrapped)
    }
    // continue without metrics, or fix the conflict and retry
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify MeterProvider is non-nil and functional before calling Init
if cfg.MeterProvider == nil {
    cfg.MeterProvider = otel.GetMeterProvider()
}

Try / catch

if err := obs.Init(cfg); err != nil {
    log.Errorf("redisotel init failed: %v", err)
    if root := errors.Unwrap(err); root != nil {
        log.Errorf("root cause: %v", root)
    }
    // degrade gracefully without metrics
}

Prevention

When it happens

Trigger: Calling GetObservabilityInstance().Init(cfg) where at least one enabled metric group triggers an OTel SDK instrument-creation error inside createRecorder.

Common situations: Another part of the application already registered an instrument with the same name but conflicting metadata (unit, description, or instrument type); the MeterProvider is nil, shut down, or broken; invalid custom bucket boundaries in HistogramAggregation configuration.

Related errors


AI-assisted analysis of go-redis/redis@36d97525cd (2026-08-06). Data as JSON: /data/errors/299a311ac8c3077e.json. Report an issue: GitHub.