redis / node-redis

Redis Node.js client
https://redis.js.org/
MIT License
16.95k stars 1.89k forks source link

Throw exception "cannot read properties of null" when using `xReadGroup` #2865

Open emptizen opened 2 weeks ago

emptizen commented 2 weeks ago

Description

Here is the exception:

"TypeError: Cannot read properties of null (reading 'length')\n    at transformTuplesReply  ***
 at transformStreamMessageReply (*** )\n    at Array.map (<anonymous>)\n    at transformStreamMessagesReply (***)\n    at ***@redis/client/dist/lib/commands/generic-transformers.js:95:19\n    at Array.map (<anonymous>)\n    at Object.transformStreamsMessagesReply

The function transformTuplesReply of generic-transform.js didn't handle the null raw reply from the stream api.

// in generic-transform.js 
function transformTuplesReply(reply) {
    const message = Object.create(null);
    for (let i = 0; i < reply.length; i += 2) {
        message[reply[i].toString()] = reply[i + 1];
    }
    return message;
}

Node.js Version

v20.16.0

Redis Server Version

6.2.6

Node Redis Version

redis@4.7.0

Platform

MacOS, Linux

Logs

"TypeError: Cannot read properties of null (reading 'length')\n    at transformTuplesReply  ***
 at transformStreamMessageReply (*** )\n    at Array.map (<anonymous>)\n    at transformStreamMessagesReply (***)\n    at ***@redis/client/dist/lib/commands/generic-transformers.js:95:19\n    at Array.map (<anonymous>)\n    at Object.transformStreamsMessagesReply
emptizen commented 2 weeks ago

Additional, I found another situation that stream read will return null.

By design, Redis doesn't prevent the deletion of entries that are present in the stream's PELs. When this happens, the PELs retain the deleted entries' IDs, but the actual entry payload is no longer available. Therefore, when reading such PEL entries, Redis will return a null value in place of their respective data. https://redis.io/docs/latest/commands/xreadgroup/