From d6d8ecf5b20c6144611d6d456d88d8db4c53fbb2 Mon Sep 17 00:00:00 2001 From: abhinavmir Date: Mon, 24 Aug 2026 19:40:06 -0700 Subject: [PATCH] Return 0 from SortedSetRemove(Async) for an empty member array ZREM needs one member or more. An empty array built a one-argument ZREM. The server refused it with "wrong number of arguments". In a transaction this became EXECABORT. An empty array now returns 0 and does not go to the server. A null array still throws an ArgumentNullException. The exception now names the "members" parameter. Before, it named the "values" parameter of the Message.Create overload. This matches SetRemove(Async). --- src/StackExchange.Redis/RedisDatabase.cs | 4 ++++ .../SortedSetTests.cs | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/StackExchange.Redis/RedisDatabase.cs b/src/StackExchange.Redis/RedisDatabase.cs index 91c99d5667..172dd3c8d8 100644 --- a/src/StackExchange.Redis/RedisDatabase.cs +++ b/src/StackExchange.Redis/RedisDatabase.cs @@ -2718,6 +2718,8 @@ public bool SortedSetRemove(RedisKey key, RedisValue member, CommandFlags flags public long SortedSetRemove(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) { + if (members == null) throw new ArgumentNullException(nameof(members)); + if (members.Length == 0) return 0; var msg = Message.Create(Database, flags, RedisCommand.ZREM, key, members); return ExecuteSync(msg, ResultProcessor.Int64); } @@ -2730,6 +2732,8 @@ public Task SortedSetRemoveAsync(RedisKey key, RedisValue member, CommandF public Task SortedSetRemoveAsync(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) { + if (members == null) throw new ArgumentNullException(nameof(members)); + if (members.Length == 0) return CompletedTask.FromResult(0, asyncState); var msg = Message.Create(Database, flags, RedisCommand.ZREM, key, members); return ExecuteAsync(msg, ResultProcessor.Int64); } diff --git a/tests/StackExchange.Redis.Tests/SortedSetTests.cs b/tests/StackExchange.Redis.Tests/SortedSetTests.cs index 684ecf0bff..b8009748ce 100644 --- a/tests/StackExchange.Redis.Tests/SortedSetTests.cs +++ b/tests/StackExchange.Redis.Tests/SortedSetTests.cs @@ -1508,4 +1508,26 @@ public async Task SortedSetUpdate() Assert.True(await db.SortedSetUpdateAsync(key, member, 1)); Assert.Equal(1, await db.SortedSetUpdateAsync(key, values)); } + + [Fact] + public async Task SortedSetRemoveArgTests() + { + await using var conn = Create(); + + var db = conn.GetDatabase(); + var key = Me(); + + RedisValue[]? members = null; + var ex = Assert.Throws(() => db.SortedSetRemove(key, members!)); + Assert.Equal("members", ex.ParamName); + ex = await Assert.ThrowsAsync(async () => await db.SortedSetRemoveAsync(key, members!).ForAwait()).ForAwait(); + Assert.Equal("members", ex.ParamName); + + members = []; + Assert.Equal(0, db.SortedSetRemove(key, members)); + + var pending = db.SortedSetRemoveAsync(key, members); + Assert.True(pending.IsCompleted); // sync; never reaches the server + Assert.Equal(0, await pending.ForAwait()); + } }