redis/redis-rb · error · NotImplementedError

Redis::Cluster doesn't implement #connection

Error message

Redis::Cluster doesn't implement #connection

What it means

Redis::Cluster overrides #connection to always raise NotImplementedError. A cluster client is a multiplexer over many per-node connections managed by the redis-cluster-client gem, so there is no single connection whose host/port/path could be reported. The override makes code written for the standalone Redis client fail loudly instead of reading a misleading connection hash.

Source

Thrown at cluster/lib/redis/cluster.rb:48

      # @param error_message [String]
      def initialize(errors, error_message = 'Command errors were replied on any node')
        @errors = errors
        super(error_message)
      end
    end

    # Raised when cluster client can't select node.
    class AmbiguousNodeError < BaseError
    end

    class TransactionConsistencyError < BaseError
    end

    class NodeMightBeDown < BaseError
    end

    def connection
      raise NotImplementedError, "Redis::Cluster doesn't implement #connection"
    end

    # Create a new client instance
    #
    # @param [Hash] options
    # @option options [Float] :timeout (5.0) timeout in seconds
    # @option options [Float] :connect_timeout (same as timeout) timeout for initial connect in seconds
    # @option options [Symbol] :driver Driver to use, currently supported: `:ruby`, `:hiredis`
    # @option options [Integer, Array<Integer, Float>] :reconnect_attempts Number of attempts trying to connect,
    #   or a list of sleep duration between attempts.
    # @option options [Boolean] :inherit_socket (false) Whether to use socket in forked process or not
    # @option options [Array<String, Hash{Symbol => String, Integer}>] :nodes List of cluster nodes to contact
    # @option options [Boolean] :replica Whether to use readonly replica nodes in Redis Cluster or not
    # @option options [Symbol] :replica_affinity scale reading strategy, currently supported: `:random`, `:latency`
    # @option options [String] :fixed_hostname Specify a FQDN if cluster mode enabled and
    #   client has to connect nodes via single endpoint with SSL/TLS
    # @option options [Class] :connector Class of custom connector
    # @option options [String, Array<String>, false] :driver_info Identity a library built on top of

View on GitHub (pinned to 2ba9010b91)

Solutions

  1. Branch on client type before introspecting: call redis.connection only when the client is not a Redis::Cluster instance
  2. For cluster topology use redis.cluster(:nodes), redis.cluster(:slots), or redis.cluster(:info) instead — they query a random node and return structured data
  3. Wrap shared code in rescue NotImplementedError and fall back to a label built from the node list you configured

Example fix

# before
info = redis.connection  # => NotImplementedError when redis is a Redis::Cluster

# after
info = if redis.is_a?(Redis::Cluster)
  { cluster: redis.cluster(:info) }
else
  redis.connection
end
Defensive patterns

Strategy: type-guard

Validate before calling

info = redis.connection unless redis.is_a?(Redis::Cluster)

Type guard

def single_connection?(redis)
  !redis.is_a?(Redis::Cluster)
end

Try / catch

begin
  info = redis.connection
rescue NotImplementedError
  info = nil  # cluster client: no single connection to report
end

Prevention

When it happens

Trigger: Calling #connection on a Redis::Cluster instance: directly (redis.connection), or via shared/instrumentation code that reads redis.connection[:host]/[:port]/[:db] and is handed a client built with Redis.new(cluster: [...]). The gem's own cluster tests call it to assert the behavior (test_connection_information, test_default_id_*).

Common situations: An app migrated from standalone Redis to Redis Cluster (cluster: option or redis://cluster URLs); monitoring, APM, or logging helpers built against the standalone client that call #connection to build a client id; test suites shared between standalone and cluster clients.


AI-assisted analysis of redis/redis-rb@2ba9010b91 (2026-08-23). Data as JSON: /api/errors/0b278d3ba5568219. Report an issue: GitHub.