redis/go-redis · error

failed to create client errors metric: %w

Error message

failed to create client errors metric: %w

What it means

Returned by createRecorder when meter.Int64Counter fails to create the redis.client.errors counter, which counts errors handled by the Redis client (resiliency metric group). Init fails with 'failed to create metrics recorder' and no resiliency metrics are collected. The MeterProvider rejected instrument creation.

Source

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

			MetricConnectionHandoff,
			metric.WithDescription("Connections that have been handed off to another node (e.g after a MOVING notification)"),
		)
		if err != nil {
			return nil, fmt.Errorf("failed to create connection handoff metric: %w", err)
		}
	}

	var clientErrors metric.Int64Counter
	var maintenanceNotifications metric.Int64Counter

	if cfg.isMetricGroupEnabled(MetricGroupResiliency) {
		clientErrors, err = meter.Int64Counter(
			MetricClientErrors,
			metric.WithDescription("Number of errors handled by the Redis client"),
			metric.WithUnit("{error}"),
		)
		if err != nil {
			return nil, fmt.Errorf("failed to create client errors metric: %w", err)
		}

		maintenanceNotifications, err = meter.Int64Counter(
			MetricMaintenanceNotifications,
			metric.WithDescription("Number of maintenance notifications received"),
			metric.WithUnit("{notification}"),
		)
		if err != nil {
			return nil, fmt.Errorf("failed to create maintenance notifications metric: %w", err)
		}
	}

	var connectionWaitTime metric.Float64Histogram
	var connectionClosed metric.Int64Counter
	var connectionPendingReqs metric.Int64UpDownCounter // OTel semconv: UpDownCounter

	if cfg.isMetricGroupEnabled(MetricGroupConnectionAdvanced) {
		var connectionWaitTimeOpts []metric.Float64HistogramOption

View on GitHub (pinned to c5cad058c7)

Solutions

  1. Guarantee a live MeterProvider before Init; do not call provider.Shutdown() earlier in startup
  2. Check for another component already registering redis.client.errors and remove the duplicate
  3. Read the wrapped error (errors.Unwrap) and otel global error-handler logs to pinpoint the SDK rejection
  4. Keep otel module versions aligned across go.mod files
  5. Temporarily disable MetricGroupFlagResiliency to confirm group-specific failure

Example fix

// before
err := obs.Init(&redisotel.Config{Enabled: true}) // MetricGroupFlagResiliency set, provider stopped
// after
// start provider first, then init
provider := sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader))
err := obs.Init(&redisotel.Config{Enabled: true, MetricGroups: redisotel.MetricGroupFlagResiliency, MeterProvider: provider})
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure provider active
if err := provider.ForceFlush(context.Background()); err != nil {
    return fmt.Errorf("meter provider not healthy: %w", err)
}

Try / catch

if err := obs.Init(cfg); err != nil {
    if strings.Contains(err.Error(), "client errors metric") {
        cfg.MetricGroups &^= redisotel.MetricGroupFlagResiliency
        err = obs.Init(cfg) // retry without resiliency group
    }
}

Prevention

When it happens

Trigger: Init with MetricGroupFlagResiliency enabled while the MeterProvider is shut down or misconfigured; duplicate instrument registration of redis.client.errors with a conflicting unit ({error}) in providers that enforce uniqueness.

Common situations: Applications wiring multiple observability shims (extra/redisprometheus plus redisotel-native) that register overlapping metric names; providers swapped or stopped during test cleanup before Init runs.

Related errors


AI-assisted analysis of redis/go-redis@c5cad058c7 (2026-09-01). Data as JSON: /api/errors/0281ee713ae7d95b. Report an issue: GitHub.