redis/redis-rb · error · ArgumentError
can't supply both nx and xx
Error message
can't supply both nx and xx
What it means
geoadd maps the nx:/xx: keywords to the server's GEOADD NX and XX flags. NX means 'only add new members, never update existing ones'; XX means 'only update existing members, never add' — mutually exclusive by definition. Passing both truthy raises ArgumentError 'can't supply both nx and xx' client-side before anything is sent (the server would reject NX XX too).
Source
Thrown at lib/redis/commands/geo.rb:15
# frozen_string_literal: true
class Redis
module Commands
module Geo
# Adds the specified geospatial items (latitude, longitude, name) to the specified key
#
# @param [String] key
# @param [Array] member arguemnts for member or members: longitude, latitude, name
# @param [Boolean] nx don't update already existing elements, always add new ones (since Redis 6.2)
# @param [Boolean] xx only update elements that already exist, never add new ones (since Redis 6.2)
# @param [Boolean] ch modify the return value to the number of changed elements (since Redis 6.2)
# @return [Integer] number of elements added to the sorted set, or changed when `ch` is set
def geoadd(key, *member, nx: false, xx: false, ch: false)
raise ArgumentError, "can't supply both nx and xx" if nx && xx
args = [:geoadd, key]
args << "NX" if nx
args << "XX" if xx
args << "CH" if ch
args.concat(member)
send_command(args)
end
# Returns geohash string representing position for specified members of the specified key.
#
# @param [String] key
# @param [String, Array<String>] member one member or array of members
# @return [Array<String, nil>] returns array containg geohash string if member is present, nil otherwise
def geohash(key, member)
send_command([:geohash, key, member])
end
View on GitHub (pinned to 2ba9010b91)
Solutions
- Pick one semantic: nx: true (add-only) or xx: true (update-only), never both
- When merging option hashes, resolve conflicts explicitly: delete :nx if :xx is set (or vice versa) before the call
- ch: true composes with either flag — use it freely when you need changed-element counts
Example fix
# before
redis.geoadd('Sicily', 13.36, 38.11, 'Palermo', nx: true, xx: true) # ArgumentError
# after
redis.geoadd('Sicily', 13.36, 38.11, 'Palermo', nx: true, ch: true) Defensive patterns
Strategy: validation
Validate before calling
opts = { nx: nx, xx: xx, ch: ch }.compact
opts.delete(:nx) if opts[:xx] # resolve the conflict explicitly: xx wins
redis.geoadd(key, *member, **opts) Try / catch
begin redis.geoadd(key, *member, nx: nx, xx: xx) rescue ArgumentError => e raise if e.message != "can't supply both nx and xx" redis.geoadd(key, *member, xx: true) # apply one semantic end
Prevention
- Never merge nx/xx from independent sources without a conflict rule
- Pick one flag per call site and state the intent in a comment or wrapper name
- Remember ch composes with either flag
When it happens
Trigger: redis.geoadd('Sicily', 13.36, 38.11, 'Palermo', nx: true, xx: true); option hashes merged from defaults plus user input where both keys end up set.
Common situations: Config-driven option merging (default nx: true, user overrides xx: true); wrappers around SET-style APIs where nx/xx pairs are familiar; enabling both flags 'to be safe'.
Related errors
- wrong number of arguments
- ranges must be given as start/stop pairs
- logic must be :and or :or
- value is required for the MATCH operation
- count argument must be specified
AI-assisted analysis of redis/redis-rb@2ba9010b91 (2026-08-23).
Data as JSON: /api/errors/30ce1b4a942f2c78.
Report an issue: GitHub.