{"record":{"id":"78c876947f165a37","repo":"redis/go-redis","slug":"failed-to-create-connection-handoff-metric-w","errorCode":null,"errorMessage":"failed to create connection handoff metric: %w","messagePattern":"failed to create connection handoff metric: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"extra/redisotel-native/redisotel.go","lineNumber":241,"sourceCode":"\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\"),\n\t\t\tmetric.WithUnit(\"{error}\"),\n\t\t)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to create client errors metric: %w\", err)\n\t\t}\n\n\t\tmaintenanceNotifications, err = meter.Int64Counter(\n\t\t\tMetricMaintenanceNotifications,","sourceCodeStart":223,"sourceCodeEnd":259,"githubUrl":"https://github.com/redis/go-redis/blob/c5cad058c72f58370553b48566302303cf8a2e89/extra/redisotel-native/redisotel.go#L223-L259","documentation":"Returned by createRecorder when meter.Int64Counter fails to create the redis.client.connection.handoff counter, which counts connections handed off to another node after MOVING maintenance notifications. Init aborts with 'failed to create metrics recorder' and observability stays disabled. The failure originates in the MeterProvider's instrument registration.","triggerScenarios":"Init with MetricGroupFlagConnectionBasic enabled while the configured (or global) MeterProvider has been Shutdown, is a stub, or rejects the instrument (e.g. duplicate name registered with different options in providers that validate this).","commonSituations":"Startup ordering bugs where telemetry is shut down before Redis clients init; two instrumentation packages registering the same metric name; minimal test MeterProviders that error on any registration.","solutions":["Initialize otel MeterProvider before redisotel Init and do not shut it down until after redisotel Shutdown","Search the codebase for duplicate registrations of redis.client.connection.handoff and reconcile name/unit/description","Inspect the wrapped error and otel's global error handler output for the provider's reason","Pin go.opentelemetry.io/otel versions consistently across all modules (go mod tidy)","As a stopgap, clear the MetricGroupFlagConnectionBasic bit in Config.MetricGroups"],"exampleFix":"// before\ndefer provider.Shutdown()\nobs.Init(cfg) // runs after shutdown in some code path\n// after\nif err := obs.Init(cfg); err != nil { log.Fatal(err) }\nruntime.AddCleanup or explicit ordered teardown: obs.Shutdown() then provider.Shutdown()","handlingStrategy":"validation","validationCode":"if cfg.Enabled && cfg.MeterProvider == nil {\n    cfg.MeterProvider = globalSDKMeterProvider // set during app bootstrap\n}\nif globalSDKMeterProvider == nil { return errors.New(\"no metric SDK configured\") }","typeGuard":null,"tryCatchPattern":"err := obs.Init(cfg)\nif err != nil {\n    log.Printf(\"observability disabled (handoff metric): %v\", err)\n}","preventionTips":["Bootstrap order: meter provider -> redisotel Init -> redis clients","Do not register redis.client.connection.handoff elsewhere","Check and log Init errors","Keep otel versions uniform"],"tags":["opentelemetry","metrics","initialization","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"}