IndexOutOfBoundsException on reading PENDING Array[Byte] message
See original GitHub issueExpected behavior
Possibly a null for a message value could be returned instead of an exception.
Actual behavior
An exception is thrown
[ERROR][o.r.c.h.CommandDecoder][redisson-netty-2-15] - Unable to decode data. channel: [id: 0xa009e266, L:/127.0.0.1:60975 - R:localhost/127.0.0.1:7379], reply: ReplayingDecoderByteBuf(ridx=66, widx=97), command: (XREADGROUP), promise: RedissonPromise [promise=ImmediateEventExecutor$ImmediatePromise@39d142a8(incomplete)], params: [GROUP, my-stream-group, my-consumer, COUNT, 10, BLOCK, 10000, STREAMS, my-stream, 0]
java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
	at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
	at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
	at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
	at java.base/java.util.Objects.checkIndex(Objects.java:372)
	at java.base/java.util.ArrayList.get(ArrayList.java:459)
	at org.redisson.client.protocol.decoder.StreamObjectMapReplayDecoder.decode(StreamObjectMapReplayDecoder.java:46)
	at org.redisson.client.protocol.decoder.StreamObjectMapReplayDecoder.decode(StreamObjectMapReplayDecoder.java:32)
	at org.redisson.client.protocol.decoder.MapEntriesDecoder.decode(MapEntriesDecoder.java:50)
	at org.redisson.client.protocol.decoder.ListMultiDecoder2.decode(ListMultiDecoder2.java:47)
	at org.redisson.client.handler.CommandDecoder.decodeList(CommandDecoder.java:436)
	at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:392)
	at org.redisson.client.handler.CommandDecoder.decodeList(CommandDecoder.java:427)
	at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:392)
	at org.redisson.client.handler.CommandDecoder.decodeList(CommandDecoder.java:427)
	at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:392)
	at org.redisson.client.handler.CommandDecoder.decodeList(CommandDecoder.java:427)
	at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:392)
	at org.redisson.client.handler.CommandDecoder.decodeList(CommandDecoder.java:427)
	at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:392)
	at org.redisson.client.handler.CommandDecoder.decodeCommand(CommandDecoder.java:198)
	at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:137)
	at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:113)
	at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:507)
	at io.netty.handler.codec.ReplayingDecoder.callDecode(ReplayingDecoder.java:366)
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1372)
	at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1235)
	at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1284)
	at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:507)
	at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:446)
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:829)
Steps to reproduce or test case
- I had a steam consumer that had both new and PENDING messages.
 - Then I cleaned up my stream from the old messages using 
XTRIM my-stream MINID 1633844273000-0command. All the events up to this point have been removed. 
It happened that some of the PENDING messages were also removed by XTRIM command. Still, they are present in PENDING list of my consumer, but the values of the messages are nil.
>> XREADGROUP GROUP my-stream-group my-consumer COUNT 10 BLOCK 1000 STREAMS my-stream 0
1) 1) "my-stream"
   2) 1) 1) "1632735948072-0"
         2) (nil)
      2) 1) "1632735948188-0"
         2) (nil)
When I try to look for data for one of those nil events (1632735948072-0), I do not find them, but Redis is providing me newer message:
>> XREAD COUNT 1 BLOCK 1000 STREAMS my-stream 1632735948072-0
1) 1) "my-stream"
   2) 1) 1) "1633931405049-0"
         2) 1) "schema"
            2) "\nS\n$f69b9f8f-2998-4f99-806d-978150a20af0\x12$4d39171e-f7ea-48b3-a1de-bf2e48fff674\x18\xbd\xcd\x9a\xef\xc6/\x12Bk-ff4f6d70f50e747bd1ece8002ee8ed0344f59b6243e0d70d76fb912701de27c2\x1aBk-da8e85720f18335ccf72a11e955ea97d5456ca0630472a6f2f50dd9a968ea44e"
I understand this looks like Redis bug and PENDING should not reference the message that no longer exists.
But I think Redisson could handle better this case and return at least null as a message value instead of throwing an exception. The reason is, I am reading 10 messages and only 1 of them can be problematic, while now the whole XREADGROUP command blows, and I am unable to handle that problematic message programmatically, e.g. acknowledge this message as having wrong message value.
Redis version 6.2.5
Redisson version 3.16.3
Redisson configuration
new Config().setCodec(ByteArrayCodec.INSTANCE)
Issue Analytics
- State:
 - Created 2 years ago
 - Comments:6 (3 by maintainers)
 

Top Related StackOverflow Question
it returns message, but without any data.
Fixed! Thanks for report