redis/go-redis · error

failed to create connection closed metric: %w

Error message

failed to create connection closed metric: %w

What it means

Returned by createRecorder when meter.Int64Counter fails to create the redis.client.connection.closed counter, which tracks the number of closed pool connections. Init aborts and observability remains uninitialized. As with the other recorder errors, the MeterProvider refused to register the instrument.

Source

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

		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)
		}
		connectionWaitTime = connectionWaitTimeConv.Inst()

		connectionClosed, err = meter.Int64Counter(
			MetricConnectionClosed,
			metric.WithDescription("The number of connections that have been closed"),
			metric.WithUnit("{connection}"),
		)
		if err != nil {
			return nil, fmt.Errorf("failed to create connection closed metric: %w", err)
		}

		connectionPendingReqs, err = meter.Int64UpDownCounter(
			dbconv.ClientConnectionPendingRequests{}.Name(),
			metric.WithDescription(dbconv.ClientConnectionPendingRequests{}.Description()),
			metric.WithUnit(dbconv.ClientConnectionPendingRequests{}.Unit()),
		)
		if err != nil {
			return nil, fmt.Errorf("failed to create connection pending requests metric: %w", err)
		}
	}

	var pubsubMessages metric.Int64Counter

	if cfg.isMetricGroupEnabled(MetricGroupPubSub) {
		pubsubMessages, err = meter.Int64Counter(
			MetricPubSubMessages,
			metric.WithDescription("The number of Pub/Sub messages sent or received"),

View on GitHub (pinned to c5cad058c7)

Solutions

  1. Confirm the MeterProvider passed in Config.MeterProvider (or the global one) is operational before Init
  2. Remove or rename any duplicate registration of redis.client.connection.closed
  3. Inspect the wrapped error for the provider's reason and fix the provider setup
  4. Keep a single metrics solution or ensure names/units do not collide across packages
  5. Clear MetricGroupFlagConnectionAdvanced in Config.MetricGroups as an isolation step or workaround

Example fix

// before
err := obs.Init(&redisotel.Config{Enabled: true, MetricGroups: redisotel.MetricGroupFlagConnectionAdvanced})
// after
if err := obs.Init(&redisotel.Config{Enabled: true, MetricGroups: redisotel.MetricGroupFlagConnectionAdvanced, MeterProvider: liveProvider}); err != nil {
    log.Fatalf("redisotel init: %v", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

if cfg.MetricGroups&redisotel.MetricGroupFlagConnectionAdvanced != 0 && cfg.MeterProvider == nil && otel.GetMeterProvider() == nil {
    return errors.New("no meter provider configured")
}

Try / catch

if err := obs.Init(cfg); err != nil {
    log.Printf("redisotel init failed: %v", err)
    // run without metrics rather than crashing
}

Prevention

When it happens

Trigger: Init with MetricGroupFlagConnectionAdvanced enabled while the MeterProvider is stopped or misconfigured; a strict provider that rejects the instrument name/unit ({connection}); duplicate registration by another package.

Common situations: Metric-name collisions when both extra/redisprometheus and redisotel-native are initialized; ordering issues where telemetry teardown precedes client init; buggy custom MeterProvider implementations.

Understand the failure class

Related errors


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