{"record":{"id":"627e71f5f7c435e8","repo":"redis/go-redis","slug":"failed-to-create-connection-relaxed-timeout-metric","errorCode":null,"errorMessage":"failed to create connection relaxed timeout metric: %w","messagePattern":"failed to create connection relaxed timeout metric: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"extra/redisotel-native/redisotel.go","lineNumber":233,"sourceCode":"\t\tif cfg.histAggregation == HistogramAggregationExplicitBucket {\n\t\t\tconnectionCreateTimeOpts = append(connectionCreateTimeOpts,\n\t\t\t\tmetric.WithExplicitBucketBoundaries(cfg.bucketsConnectionCreateTime...),\n\t\t\t)\n\t\t}\n\t\tvar connectionCreateTimeConv dbconv.ClientConnectionCreateTime\n\t\tconnectionCreateTimeConv, err = dbconv.NewClientConnectionCreateTime(meter, connectionCreateTimeOpts...)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to create connection create time histogram: %w\", err)\n\t\t}\n\t\tconnectionCreateTime = connectionCreateTimeConv.Inst()\n\n\t\tconnectionRelaxedTimeout, err = meter.Int64UpDownCounter(\n\t\t\tMetricConnectionRelaxedTimeout,\n\t\t\tmetric.WithDescription(\"How many times the connection timeout has been increased/decreased (after a server maintenance notification)\"),\n\t\t\tmetric.WithUnit(\"{relaxation}\"),\n\t\t)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to create connection relaxed timeout metric: %w\", err)\n\t\t}\n\n\t\tconnectionHandoff, err = meter.Int64Counter(\n\t\t\tMetricConnectionHandoff,\n\t\t\tmetric.WithDescription(\"Connections that have been handed off to another node (e.g after a MOVING notification)\"),\n\t\t)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to create connection handoff metric: %w\", err)\n\t\t}\n\t}\n\n\tvar clientErrors metric.Int64Counter\n\tvar maintenanceNotifications metric.Int64Counter\n\n\tif cfg.isMetricGroupEnabled(MetricGroupResiliency) {\n\t\tclientErrors, err = meter.Int64Counter(\n\t\t\tMetricClientErrors,\n\t\t\tmetric.WithDescription(\"Number of errors handled by the Redis client\"),","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/redis/go-redis/blob/c5cad058c72f58370553b48566302303cf8a2e89/extra/redisotel-native/redisotel.go#L215-L251","documentation":"Returned by createRecorder when meter.Int64UpDownCounter fails to create the redis.client.connection.relaxed_timeout UpDownCounter, a go-redis-specific gauge tracking timeout relaxations after server maintenance notifications. Init aborts, so connection-basic metrics are not installed. Root cause is again a failing MeterProvider.","triggerScenarios":"Init with MetricGroupFlagConnectionBasic enabled against a shut-down, misconfigured, or instrument-rejecting MeterProvider; conflicting prior registration of an instrument with the same name but different unit/description in some strict providers.","commonSituations":"Re-initializing observability after Shutdown in long-running services; registering the same metric name through two different libraries with conflicting attributes; test harnesses replacing the global provider mid-run.","solutions":["Call Shutdown() on the ObservabilityInstance before re-running Init (Init errors with 'already initialized' otherwise, but provider conflicts can surface here too)","Ensure only one library registers the redis.client.connection.relaxed_timeout instrument name","Provide a healthy MeterProvider via cfg.MeterProvider and keep it alive for the process lifetime","Unwrap the error for the SDK-level reason and fix the provider configuration","Disable MetricGroupFlagConnectionBasic if these maintenance-notification metrics are not needed"],"exampleFix":"// before\n_ = obs.Init(cfg) // provider already Shutdown() earlier\n// after\nif err := obs.Shutdown(); err != nil { /* log */ }\nprovider = sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader))\nif err := obs.Init(&redisotel.Config{Enabled: true, MeterProvider: provider}); err != nil { /* log */ }","handlingStrategy":"try-catch","validationCode":"if cfg.MetricGroups&redisotel.MetricGroupFlagConnectionBasic != 0 && !obsEnabledFreshly {\n    // ensure obs.Shutdown() was called before re-Init\n}","typeGuard":null,"tryCatchPattern":"if err := obs.Init(cfg); err != nil {\n    otel.Handle(err)\n    // degrade: continue running without relaxed-timeout metrics\n}","preventionTips":["Pair every Init with a prior Shutdown on reinitialization","Register each redis.client.* metric name from exactly one package","Check Init's return error","Keep the MeterProvider alive for the process lifetime"],"tags":["opentelemetry","metrics","maintenance-notifications","go"],"backgroundTag":"otel-instrument-creation-failed","analyzedSha":"c5cad058c72f58370553b48566302303cf8a2e89","analyzedAt":"2026-09-01T06:50:53.388Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}