redisson/redisson · error · InvalidDataAccessApiUsageException
%s PUSHX only allows one value!
Error message
%s PUSHX only allows one value!
What it means
RedissonReactiveListCommands.push(PushCommand) throws InvalidDataAccessApiUsageException('<dir> PUSHX only allows one value!') when the command has upsert=false (meaning LPUSHX/RPUSHX semantics) but carries more than one value. Redis' PUSHX commands accept exactly one value, unlike plain LPUSH/RPUSH.
Source
Thrown at redisson-spring/redisson-spring-data/redisson-spring-data-20/src/main/java/org/redisson/spring/data/connection/RedissonReactiveListCommands.java:68
private static final RedisStrictCommand<Long> RPUSH = new RedisStrictCommand<Long>("RPUSH");
private static final RedisStrictCommand<Long> LPUSH = new RedisStrictCommand<Long>("LPUSH");
private static final RedisStrictCommand<Long> RPUSHX = new RedisStrictCommand<Long>("RPUSHX");
private static final RedisStrictCommand<Long> LPUSHX = new RedisStrictCommand<Long>("LPUSHX");
RedissonReactiveListCommands(CommandReactiveExecutor executorService) {
super(executorService);
}
@Override
public Flux<NumericResponse<PushCommand, Long>> push(Publisher<PushCommand> commands) {
return execute(commands, command -> {
Assert.notNull(command.getKey(), "Key must not be null!");
Assert.notEmpty(command.getValues(), "Values must not be null or empty!");
if (!command.getUpsert() && command.getValues().size() > 1) {
throw new InvalidDataAccessApiUsageException(
String.format("%s PUSHX only allows one value!", command.getDirection()));
}
RedisStrictCommand<Long> redisCommand;
List<Object> params = new ArrayList<Object>();
params.add(toByteArray(command.getKey()));
params.addAll(command.getValues().stream().map(v -> toByteArray(v)).collect(Collectors.toList()));
if (ObjectUtils.nullSafeEquals(Direction.RIGHT, command.getDirection())) {
if (command.getUpsert()) {
redisCommand = RPUSH;
} else {
redisCommand = RPUSHX;
}
} else {
if (command.getUpsert()) {
redisCommand = LPUSH;View on GitHub (pinned to 91188987c2)
Solutions
- Split multiple values into one PushX command per value, each with a single-element values list.
- If the key is guaranteed to exist, drop untilAbsent()/upsert(false) so plain LPUSH/RPUSH handles multiple values.
- Validate values.size() <= 1 before submitting an upsert=false command.
Example fix
// before
PushCommand cmd = PushCommand.push(key, Direction.RIGHT, v1, v2).untilAbsent(true);
listCommands.push(Flux.just(cmd)); // throws: RIGHT PUSHX only allows one value!
// after
Flux<PushCommand> cmds = Flux.just(
PushCommand.push(key, Direction.RIGHT, v1).untilAbsent(true),
PushCommand.push(key, Direction.RIGHT, v2).untilAbsent(true));
listCommands.push(cmds); Defensive patterns
Strategy: validation
Validate before calling
// split multi-value upsert=false pushes into single-value commands
List<PushCommand> safe = new ArrayList<>();
if (!cmd.getUpsert() && cmd.getValues().size() > 1) {
for (ByteBuffer v : cmd.getValues()) {
safe.add(PushCommand.push(cmd.getKey(), cmd.getDirection(), v).untilAbsent(true));
}
} else {
safe.add(cmd);
} Type guard
boolean isValidPushX(PushCommand cmd) {
return cmd.getUpsert() || cmd.getValues().size() <= 1;
} Prevention
- Remember PUSHX (LPUSHX/RPUSHX) is single-value in Redis; only plain LPUSH/RPUSH accept many
- Encapsulate push-command construction in one helper that enforces the PUSHX rule
When it happens
Trigger: Building a PushCommand via RedisListCommands.PushCommand.push(key, value, direction).untilAbsent(true) — or setting upsert(false) — with a values list of length > 1, then executing it through the reactive list commands.
Common situations: Reusing a generic 'push many values' helper for both upsert and non-upsert paths; switching a working multi-value LPUSH to untilAbsent() without splitting values.
Related errors
- Unable to locate Redisson instance by name: ${jndiName}
- Command must not define expiration nor option for GETSET.
- Expiration must not be null!
- NOT operation doesn't support more than single source key
- %s PUSHX only allows one value!
AI-assisted analysis of redisson/redisson@91188987c2 (2026-08-14).
Data as JSON: /api/errors/7ea566bd8d6eccc1.
Report an issue: GitHub.