redis/go-redis · error

failed to create maintenance notifications metric: %w

Error message

failed to create maintenance notifications metric: %w

What it means

Returned by createRecorder when meter.Int64Counter fails to create the redis.client.maintenance.notifications counter, which counts RESP3 maintenance notifications received (MOVING, MIGRATING, etc.). Init aborts, leaving observability uninitialized. Cause is a MeterProvider that fails instrument registration.

Source

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

	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
		if cfg.histAggregation == HistogramAggregationExplicitBucket {
			connectionWaitTimeOpts = append(connectionWaitTimeOpts,
				metric.WithExplicitBucketBoundaries(cfg.bucketsConnectionWaitTime...),
			)
		}
		var connectionWaitTimeConv dbconv.ClientConnectionWaitTime
		connectionWaitTimeConv, err = dbconv.NewClientConnectionWaitTime(meter, connectionWaitTimeOpts...)
		if err != nil {
			return nil, fmt.Errorf("failed to create connection wait time histogram: %w", err)

View on GitHub (pinned to c5cad058c7)

Solutions

  1. Start the metric SDK provider before redisotel Init and order shutdown as obs.Shutdown() then provider.Shutdown()
  2. Verify no duplicate redis.client.maintenance.notifications registration exists
  3. Unwrap the error to read the provider's specific failure and correct provider configuration
  4. Run go mod tidy / consistent otel versions across modules
  5. Drop MetricGroupFlagResiliency from Config.MetricGroups if the metric is unnecessary

Example fix

// before
provider.Shutdown(ctx)
obs.Init(cfg)
// after
obs.Init(cfg)
// later, at exit:
obs.Shutdown()
provider.Shutdown(ctx)
Defensive patterns

Strategy: validation

Validate before calling

if cfg.Enabled && meterProvider == nil {
    return errors.New("redisotel: MeterProvider required when Enabled")
}

Type guard

if _, ok := meterProvider.(*sdkmetric.MeterProvider); !ok { /* install real SDK */ }

Try / catch

if err := obs.Init(cfg); err != nil {
    otel.Handle(err)
    log.Printf("maintenance-notification metrics unavailable: %v", err)
}

Prevention

When it happens

Trigger: Init with MetricGroupFlagResiliency enabled against a shut-down/no-op/strict MeterProvider, or duplicate registration of the metric name with the conflicting unit {notification}.

Common situations: Deployments with maintenance-notification monitoring wired to a custom exporter whose provider rejects the instrument; test suites tearing down the metric SDK before the Redis clients init; otel version skew between dbconv-using modules.

Related errors


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