Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] The property 'options.family' must be one of: 0, 4, 6. Received '4' #2704

Open
nktnet1 opened this issue Feb 12, 2024 · 4 comments
Open

Comments

@nktnet1
Copy link

nktnet1 commented Feb 12, 2024

Description

When a REDIS_URL specifies a "family" in the URL, e.g.

redis://@redis:50004/?family=4

it is not type-casted to number, resulting in the error

node:dns:179
          validateOneOf(options.family, 'options.family', validFamilies);
          ^

TypeError [ERR_INVALID_ARG_VALUE]: The property 'options.family' must be one of: 0, 4, 6. Received '4'
    at lookup (node:dns:179:11)
    at emitLookup (node:net:1412:5)
    at defaultTriggerAsyncIdScope (node:internal/async_hooks:464:18)
    at lookupAndConnectMultiple (node:net:1411:3)
    at node:net:1357:7
    at defaultTriggerAsyncIdScope (node:internal/async_hooks:464:18)
    at lookupAndConnect (node:net:1356:5)
    at Socket.connect (node:net:1253:5)
    at connect (node:net:236:17)
    at /home/nktnet/temp/bull/node_modules/ioredis/built/connectors/StandaloneConnector.js:54:66 {
  code: 'ERR_INVALID_ARG_VALUE'
}

Minimal, Working Test code to reproduce the issue.

const Queue = require('bull');

const myQueue = new Queue('myQueue', 'redis://@redis:50004/?family=4');

myQueue.process(() => {});

Bull version

4.12.2

Additional information

1707728023

One potential workaround could be to change the redisOptsFromUrl function

bull/lib/queue.js

Lines 319 to 341 in 60fa88f

function redisOptsFromUrl(urlString) {
let redisOpts = {};
try {
const redisUrl = url.parse(urlString, true, true);
redisOpts.port = parseInt(redisUrl.port || '6379', 10);
redisOpts.host = redisUrl.hostname;
redisOpts.db = redisUrl.pathname ? redisUrl.pathname.split('/')[1] : 0;
if (redisUrl.auth) {
const columnIndex = redisUrl.auth.indexOf(':');
redisOpts.password = redisUrl.auth.slice(columnIndex + 1);
if (columnIndex > 0) {
redisOpts.username = redisUrl.auth.slice(0, columnIndex);
}
}
if (redisUrl.query) {
redisOpts = { ...redisOpts, ...redisUrl.query };
}
} catch (e) {
throw new Error(e.message);
}
return redisOpts;
}

to typecast all numbers, e.g.

function redisOptsFromUrl(urlString) {
  let redisOpts = {};
  try {
    const redisUrl = url.parse(urlString, true, true);
    redisOpts.port = parseInt(redisUrl.port || '6379', 10);
    redisOpts.host = redisUrl.hostname;
    redisOpts.db = redisUrl.pathname ? redisUrl.pathname.split('/')[1] : 0;
    if (redisUrl.auth) {
      const columnIndex = redisUrl.auth.indexOf(':');
      redisOpts.password = redisUrl.auth.slice(columnIndex + 1);
      if (columnIndex > 0) {
        redisOpts.username = redisUrl.auth.slice(0, columnIndex);
      }
    }

    if (redisUrl.query) {
      for (let key in redisUrl.query) {
        if (!isNaN(redisUrl.query[key])) {
          redisOpts[key] = parseInt(redisUrl.query[key], 10);
        } else {
          redisOpts[key] = redisUrl.query[key];
        }
      }
    }
  } catch (e) {
    throw new Error(e.message);
  }
  return redisOpts;
}
17c17,23
<        redisOpts = { ...redisOpts, ...redisUrl.query };
---
>       for (let key in redisUrl.query) {
>         if (!isNaN(redisUrl.query[key])) {
>           redisOpts[key] = parseInt(redisUrl.query[key], 10);
>         } else {
>           redisOpts[key] = redisUrl.query[key];
>         }
>       }

although not too sure about any side effects.

@nktnet1 nktnet1 changed the title The property 'options.family' must be one of: 0, 4, 6. Received '4' [bug] The property 'options.family' must be one of: 0, 4, 6. Received '4' Feb 12, 2024
@nktnet1 nktnet1 changed the title [bug] The property 'options.family' must be one of: 0, 4, 6. Received '4' [Bug] The property 'options.family' must be one of: 0, 4, 6. Received '4' Feb 12, 2024
@manast
Copy link
Member

manast commented Feb 14, 2024

I am not sure this is an issue in Bull or in IORedis. However you should be able to workaround it by just passing the family options separately:

const myQueue = new Queue('myQueue', 'redis://@redis:50004/', { redis: { family: 4 } });

@nktnet1
Copy link
Author

nktnet1 commented Feb 14, 2024

Hi @manast,

Thanks for the reply. I use both IOredis and Bull and IOredis parses it correctly.

The issue is with this line of code for Bull, which parses all query parameters as string:

redisOpts = { ...redisOpts, ...redisUrl.query };

In development, I use family=4, but in production it's family=6, so the workaround I came up with is in the original comment where I just defined my own redisOptsFromUrl function and pass in those parsed options instead :).

Thinking back now, why does bull need the redisOptsFromUrl function to parse the URL at all?
Maybe it's sufficient to simply forward the REDIS_URL to IOredis directly?

Copy link

stale bot commented Apr 18, 2024

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Apr 18, 2024
@nktnet1
Copy link
Author

nktnet1 commented Apr 18, 2024

not stale, potentially

@stale stale bot removed the wontfix label Apr 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants