node-redis: Incorrect setReturnBuffers when parsing PubSub 'message' response

Since upgrading my redis server to 6.2.6 and redis client to 4.0.2 (from 4.0.1) I’ve been occasionally seeing the following crash: TypeError [ERR_INVALID_ARG_TYPE]: The "otherBuffer" argument must be an instance of Buffer or Uint8Array. Received type string ('message')

I’ve tracked this down to parser.optionReturnBuffers being set to false when it should be true causing the ‘message’ string to be returned as a string rather than a Buffer.

commands-queue.ts expects this to be a Buffer, and Buffer.equals throws the above NodeError.

This response comes in through parseResponse which calls this.#setReturnBuffers(). I haven’t been able to track down why this works correctly most of the time, but occasionally winds up setting parser.optionReturnBuffers to false and blowing up. Hopefully someone more familiar with the code can spot what’s going on.

Environment:

  • Node.js Version: 16.8.0
  • Redis Server Version: 6.2.6
  • Node Redis Version: 4.0.2
  • Platform: Ubuntu 20.04.3 LTS (WSL2)

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 5
  • Comments: 24 (2 by maintainers)

Commits related to this issue

Most upvoted comments

This issue is affecting our production as well, when should we expect a fix for this?

A new version with @jhiesey fix will be released tomorrow. Sorry it took so much time.

I see this issue as closed but I am getting this error for pub sub messages randomly every now and then. “The “otherBuffer” argument must be an instance of Buffer or Uint8Array.” I’ve read through this closed issue but it’s not clear to me How to resolve this? Can someone please point it out?

Thank you!

@digitalml @mifopen the issue is closed because the fix was merged to master. Unfortunately there hasn’t been a release published that includes the fix; hopefully there will be one soon. Perhaps @leibale could comment on when.

You can use my workaround in https://github.com/redis/node-redis/issues/1870#issuecomment-1057530027 for the time being

@binarymist I can’t speak for the maintainers, but my PR is a quick fix for the immediate issue. #1899 is a rewrite of the parser and is a better long term solution but I suspect it’s not quite ready.

The workaround I’m currently using is to install patch-package and add this patch file, which is equivalent to the change in #2016 at patches/@node-redis+client+1.0.4.patch:

diff --git a/node_modules/@node-redis/client/dist/lib/client/commands-queue.js b/node_modules/@node-redis/client/dist/lib/client/commands-queue.js
index 8d22295..d3e7807 100644
--- a/node_modules/@node-redis/client/dist/lib/client/commands-queue.js
+++ b/node_modules/@node-redis/client/dist/lib/client/commands-queue.js
@@ -279,7 +279,8 @@ _a = RedisCommandsQueue, _RedisCommandsQueue_maxLength = new WeakMap(), _RedisCo
 }, _RedisCommandsQueue_setReturnBuffers = function _RedisCommandsQueue_setReturnBuffers() {
     var _b, _c;
     __classPrivateFieldGet(this, _RedisCommandsQueue_parser, "f").setReturnBuffers(!!((_b = __classPrivateFieldGet(this, _RedisCommandsQueue_waitingForReply, "f").head) === null || _b === void 0 ? void 0 : _b.value.returnBuffers) ||
-        !!((_c = __classPrivateFieldGet(this, _RedisCommandsQueue_pubSubState, "f")) === null || _c === void 0 ? void 0 : _c.subscribed));
+        !!((_c = __classPrivateFieldGet(this, _RedisCommandsQueue_pubSubState, "f")) === null || _c === void 0 ? void 0 : _c.subscribed) ||
+        !!((_c = __classPrivateFieldGet(this, _RedisCommandsQueue_pubSubState, "f")) === null || _c === void 0 ? void 0 : _c.subscribing));
 }, _RedisCommandsQueue_shiftWaitingForReply = function _RedisCommandsQueue_shiftWaitingForReply() {
     if (!__classPrivateFieldGet(this, _RedisCommandsQueue_waitingForReply, "f").length) {
         throw new Error('Got an unexpected reply from Redis');