redis/redis-rb · error · Redis::Distributed::CannotDistribute
WATCH cannot be used in Redis::Distributed because the keys
Error message
WATCH cannot be used in Redis::Distributed because the keys involved need to be on the same server or because we cannot guarantee that the operation will be atomic.
What it means
Error "WATCH cannot be used in Redis::Distributed because the keys involved need to be on the same server or because we cannot guarantee that the operation will be atomic." thrown in redis/redis-rb.
Source
Thrown at lib/redis/distributed.rb:36
attr_reader :ring
def initialize(node_configs, options = {})
@tag = options[:tag] || /^\{(.+?)\}/
@ring = options[:ring] || HashRing.new
@node_configs = node_configs.map(&:dup)
@default_options = options.dup
# Schemas registered via himport_prepare, replayed to nodes that join the ring later (see
# #add_node) so ring membership changes don't leave nodes without the fieldsets that
# key-routed himport_set calls expect. Initialized before the add_node loop below.
@himport_fieldsets = {}
node_configs.each { |node_config| add_node(node_config) }
@subscribed_node = nil
@watch_key = nil
end
def node_for(key)
key = key_tag(key.to_s) || key.to_s
raise CannotDistribute, :watch if @watch_key && @watch_key != key
@ring.get_node(key)
end
def nodes
@ring.nodes
end
def add_node(options)
options = { url: options } if options.is_a?(String)
options = @default_options.merge(options)
options.delete(:tag)
options.delete(:ring)
node = Redis.new(options)
# Replay registered fieldsets before the node can receive key-routed himport_set calls:
# a node joining after a himport_prepare fan-out has neither the server-side fieldset nor
# a populated registry to self-recover from "no such fieldset".
@himport_fieldsets.each { |name, fields| node.himport_prepare(name, fields) }View on GitHub (pinned to 2ba9010b91)
Solutions
- Do not use watch/multi optimistic locking on Redis::Distributed; run the WATCH-based transaction against a single Redis instance that holds all involved keys.
- Use Redis::Cluster or a standalone Redis connection if you need WATCH semantics.
When it happens
Trigger: Thrown at lib/redis/distributed.rb:36 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of redis/redis-rb@2ba9010b91 (2026-08-23).
Data as JSON: /api/errors/24ed7165b257be24.
Report an issue: GitHub.