When using ioredis in Heroku using RedisToGo add-on, I get this error:
Unhandled rejection ReplyError: ERR invalid DB index
at ReplyParser._parseResult (/app/node_modules/ioredis/lib/parsers/javascript.js:56:14)
at ReplyParser.execute (/app/node_modules/ioredis/lib/parsers/javascript.js:174:20)
at Socket.<anonymous> (/app/node_modules/ioredis/lib/redis/event_handler.js:88:22)
at Socket.emit (events.js:107:17)
at readableAddChunk (_stream_readable.js:163:16)
at Socket.Readable.push (_stream_readable.js:126:10)
at TCP.onread (net.js:538:20)
Everything works fine on my local machine(OS X) and local redis. I'm testing this with free plan in RedisToGo.
I'm initializing ioredis(version 1.5.0) like this:
var redis = new Redis(process.env.REDIS_URL, {
retryStrategy: function(times) {
// Make reconnecting a bit more relaxed compared to default
var delay = Math.min(times * 100, 4000);
return delay;
}
});
redis://redistogo:<secret>@<secret>.redistogo.com:<port>/.redis://127.0.0.1:6379Do you have ideas of how to fix this? Redis works apparently correctly but my logs fill up with those exceptions and in general I'd like to get this resolved.
By setting the database to 0 in the url: redis://redistogo:<secret>@<secret>.redistogo.com:<port>/0 the issue goes away.
This might be an bug in parsing urls with trailing slash. Quote from RedisToGo support:
Just wanted to send you a bit more information, as I did some digging into the driver code and I have found the source of the issue. Here is some sample code from the node shell that should explain things:
var urllib = require('url'); var Redis = require('ioredis'); // Explicit database 0 > var redis = Redis('redis://redistogo:[email protected]:54321/0'); undefined > redis.get('foo', function(err, result){console.log(result);}); { _bitField: 1, _fulfillmentHandler0: [Function: successAdapter], _rejectionHandler0: [Function: errorAdapter], _progressHandler0: undefined, _promise0: [Function], _receiver0: [Circular], _settledValue: undefined } > bar // Implied database 0 > var redis2 = Redis('redis://redistogo:[email protected]:54321'); undefined > redis2.get('foo', function(err, result){console.log(result);}); { _bitField: 1, _fulfillmentHandler0: [Function: successAdapter], _rejectionHandler0: [Function: errorAdapter], _progressHandler0: undefined, _promise0: [Function], _receiver0: [Circular], _settledValue: undefined } > bar // Force parse error > var redis3 = Redis('redis://redistogo:[email protected]:54321/'); undefined > Unhandled rejection ReplyError: ERR invalid DB index at ReplyParser._parseResult (/mycomputer/vault/code/node_realm/node_modules/ioredis/lib/parsers/javascript.js:56:14) at ReplyParser.execute (/mycomputer/vault/code/node_realm/node_modules/ioredis/lib/parsers/javascript.js:174:20) at Socket.<anonymous> (/mycomputer/vault/code/node_realm/node_modules/ioredis/lib/redis/event_handler.js:88:22) at Socket.emit (events.js:107:17) at readableAddChunk (_stream_readable.js:163:16) at Socket.Readable.push (_stream_readable.js:126:10) at TCP.onread (net.js:538:20) > redis3.get('foo', function(err, result){console.log(result);}); { _bitField: 1, _fulfillmentHandler0: [Function: successAdapter], _rejectionHandler0: [Function: errorAdapter], _progressHandler0: undefined, _promise0: [Function], _receiver0: [Circular], _settledValue: undefined } > bar // Different parsed URLs > var p = url.parse('redis://redistogo:[email protected]:54321/0'); undefined > p { protocol: 'redis:', slashes: true, auth: 'redistogo:mypassword', host: 'myhost.redistogo.com:54321', port: '54321', hostname: 'myhost.redistogo.com', hash: null, search: null, query: null, pathname: '/0', path: '/0', href: 'redis://redistogo:[email protected]:54321/0' } > p.pathname.slice(1) 0 > var p2 = url.parse('redis://redistogo:[email protected]:54321'); undefined > p2 { protocol: 'redis:', slashes: true, auth: 'redistogo:mypassword', host: 'myhost.redistogo.com:54321', port: '54321', hostname: 'myhost.redistogo.com', hash: null, search: null, query: null, pathname: null, path: null, href: 'redis://redistogo:[email protected]:54321' } // p2.pathname is null, won't call .split(1) and _.defaults will be called // See code below // https://github.com/luin/ioredis/blob/master/lib/utils/index.js#L254-L285 > var p3 = url.parse('redis://redistogo:[email protected]:54321/'); undefined > p3 { protocol: 'redis:', slashes: true, auth: 'redistogo:mypassword', host: 'myhost.redistogo.com:54321', port: '54321', hostname: 'myhost.redistogo.com', hash: null, search: null, query: null, pathname: '/', path: '/', href: 'redis://redistogo:[email protected]:54321/' } > p3.pathname.slice(1) ''Looking through the documentation for the driver they list a trailing slash as a valid URL, but in this driver it is not handled correctly. Here is the example in the docs:
https://github.com/luin/ioredis/blob/master/lib/redis.js#L84
My proposed solution would be to modify this code:
https://github.com/luin/ioredis/blob/master/lib/utils/index.js#L270-L272
if (parsed.protocol === 'redis:') { result.db = (parsed.pathname !== '/') ? parsed.pathname.slice(1) : '0'; }I hope this helps explain things but please let me know if you have any further questions.
Thank you,
~John Moore
RedisToGo Support
Any idea what Version of Redis they're running at redistogo.com?
SELECT '' seems to be valid on >Redis 2.4 and defaults to 0.
It's a bug that getting a NaN db when the pathname is empty. Fixed in 1.5.1. Thanks for pointing it out.
This still happens on Heroku using v4.16.3. Adding /0 to the end of the Redis URL makes it go away.
Most helpful comment
By setting the database to 0 in the url:
redis://redistogo:<secret>@<secret>.redistogo.com:<port>/0the issue goes away.