Open elvince opened 1 year ago
"Unhandled 'error' event" means that you are not listening to 'error's... maybe you have more than one client in the code and you forgot to listen to errors on one of them?
I am having this problem too. I only have one client, and the on error is set. But it crashes anyways. Using 4.6.10 on node 20.7.0 It will error 10 or so times on the socket, then crash, each time calling the on error handler. Very easy to reproduce, just restart the docker container for redis and your client crashes.
this.client = createClient()
this.client.on('error', err => console.log('Redis Client Error', err))
this.client.on('end', () => {
console.log('Redis connection ended');
})
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\app\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\app\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\app\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\app\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
undefined
node:internal/process/promises:289
triggerUncaughtException(err, true /* fromPromise */);
^
SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\app\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
After tracing it, I think the error ultimately comes from something in your code making a get or set to redis while it is down.
I am getting around the problem by watching the ready
event and using my own state variable to skip over gets and sets while it is disconnected.
I confirm I have only 1 client and I set the error handler.
const _redisClient = createClient(conOptions);
_redisClient.on('ready', () => {
console.log('Redis is ready');
});
_redisClient.on('reconnecting', () => {
console.log('client is reconnecting');
});
_redisClient.on('end', () => {
console.log('Redis connection ended');
});
_redisClient.on('connect', () => {
global.console.log('connected');
});
_redisClient.on('error', (err) => {
console.error('Redis error: ', err);
});
_redisClient.connect();
return _redisClient;
Thanks,
In my case, it is not catch inside the error handler :(
If I shutdown the redis server, the error is properly managed: 2023-10-06T13:18:21.252432723Z Redis error: Error: read ECONNRESET 2023-10-06T13:18:21.252493923Z at TCP.onStreamRead (node:internal/stream_base_commons:217:20) { 2023-10-06T13:18:21.252499722Z errno: -104, 2023-10-06T13:18:21.252502922Z code: 'ECONNRESET', 2023-10-06T13:18:21.252505922Z syscall: 'read' 2023-10-06T13:18:21.252508922Z } 2023-10-06T13:18:21.252566422Z client is reconnecting
@leibale Any tips ? Is there a possibility that it happens when 2 command are sent at the same time? thanks,
How to fix this?
How to fix this?
If its like my solution, double check you are not trying to set or get while the connection is down. Add a global variable for yourself to check that updates
let alive=false
_redisClient.on('end', () => {
alive=false
});
_redisClient.on('ready', () => {
alive=true
});
_redisClient.on('error', (err) => {
alive=false
});
and before redisClient.set()
if (alive){
redisClient.set(etc, etc2)
}
That way you don't try to set when its dead. I made a whole wrapper class around redis so it was trivial to add a check to all of them
damn, same erro. there's no fix i see
@TDola you can use disableOfllineQueue
to achieve the same thing. See here.
@ap0sentada @bossajie @elvince I only managed to reproduce this when a client emits an error and there are no listeners (which is expected behavior). If this error is thrown in other cases, please share code that reproduces it..
@TDola you can use
disableOfllineQueue
to achieve the same thing. See here.@ap0sentada @bossajie @elvince I only managed to reproduce this when a client emits an error and there are no listeners (which is expected behavior). If this error is thrown in other cases, please share code that reproduces it..
You can use this code to reproduce the problem.
package.json
{
"name": "redis-crash-test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"run": "node index.js"
},
"type": "module",
"author": "",
"license": "ISC",
"dependencies": {
"redis": "^4.6.10"
}
}
npm install
it and run it.
import { createClient } from 'redis'
const client = createClient()
client.on('error', async err => {
console.log('Redis Client Error', err)
})
client.on('end', () => {
console.log('Redis connection ended');
})
client.on('ready', () => {
console.log('redis connected')
})
await client.connect()
const createKeys = () => {
for (let i = 0; i < 10000; i++) {
const value = JSON.stringify({test: i}, null, 2)
// purposely no await to simulate a busy async system
client.set('test-key:' + performance.now(), value)
}
}
const removeKeys = async () => {
const results = await client.keys('test-key:*')
for (const key of results) {
// no await on purpose
client.del(key)
}
}
const runner=()=>{
console.log('starting runner loop')
createKeys()
console.log('done setting keys')
removeKeys()
console.log('done deleting keys, waiting 1000')
setTimeout(()=>{runner()}, 1000)
}
process.on('SIGINT', async function() {
console.log("Caught interrupt signal");
const results = await client.keys('test-key:*')
for (const key of results) {
await client.del(key)
}
console.log("test keys cleaned")
process.exit()
})
runner()
leave it to run a little bit, like 10 seconds. Then shut down your redis manually, the script should crash most of the time. Fiddle with the timeout to adjust.
starting runner loop
done setting keys
done deleting keys, waiting 5000
starting runner loop
done setting keys
done deleting keys, waiting 5000
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
redis connected
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (E:\workspace\redis-crash-test\node_modules\@redis\client\dist\lib\client\socket.js:194:118)
at Object.onceWrapper (node:events:629:26)
at Socket.emit (node:events:514:28)
at TCP.<anonymous> (node:net:337:12)
starting runner loop
done setting keys
done deleting keys, waiting 5000
redis connected
Redis Client Error Error: read ECONNRESET
at TCP.onStreamRead (node:internal/stream_base_commons:217:20) {
errno: -4077,
code: 'ECONNRESET',
syscall: 'read'
}
node:internal/process/promises:289
triggerUncaughtException(err, true /* fromPromise */);
^
Error: read ECONNRESET
at TCP.onStreamRead (node:internal/stream_base_commons:217:20) {
errno: -4077,
code: 'ECONNRESET',
syscall: 'read'
}
Node.js v20.7.0
The real bug might be that the ready event kept getting called even though the redis server was still down. What was it connecting to?
@TDola its fine not awaiting a promise, but you'll have to catch the errors, otherwise it'll crash with "unhandled promise rejection" error..
I tried reproducing it using
import { createClient } from 'redis';
const client = await createClient()
.on('error', (err) => console.log('client error', err))
.on('ready', () => console.log('client is ready'))
.connect();
function createKeys() {
for (let i = 0; i < 10000; i++) {
client.set(`text-key${i.toString()}`, i.toString()).catch(err => {
console.error(`Error in SET ${i}`, err);
});
}
}
async function removeKeys() {
for (const key of await client.keys('test-key:*')) {
client.del(key).catch(err => {
console.error(`Error in DEL ${key}`, err);
});
}
}
function runner() {
console.log('starting runner loop');
createKeys();
console.log('done setting keys');
removeKeys();
console.log('done deleting keys, waiting 1000');
setTimeout(runner, 1000);
}
runner();
but... it works...
Your key set is using a number as the ID instead of test-key: so it won't find anything in the key search. I haven't had much coffee yet so I could be wrong in reading that. But if the catch solves it, then perfect that's easily implementable.
function createKeys() {
for (let i = 0; i < 10000; i++) {
client.set(i.toString(), i.toString()).catch(err => {
console.error(`Error in SET ${i}`, err);
});
}
}
We are using createCluster(). Maybe the issue is coming from createCluster() ?
@TDola I've fixed the example, please LMK if you find anything..
@bossajie are you listening to error
s on the cluster? i.e.:
import { createCluster } from 'redis';
const cluster = await createCluster(...)
.on('error', err => console.error('Redis Cluster Error', err)
.connect();
@leibale That's great that we are moving on this issue. It is difficult to catch issue that is not reproductible.
On TDola case, it was reproductible and you fix it by reviewing the code sample. Is there a way to catch the error on your side when it happenned so we can have more info on where to fix stuff? or the "unhandled promise rejection" bypass you error handling process?
If I properly understand, the issue can arise on promise not awaited / catched, correct? I will double check this point on my side (even if I already did it :D)
thanks
Edit: I checked and all calls are awaited. I hope we can have a way to track this kind of bugs. It seems to happen when no call are made during a long period. I'm on azure app container and I already set the timeout parameter as per your recommendations
const conOptions: RedisClientOptions = {
password: xxxx
socket: {
host: redisOptions.host,
port: 6666,
connectTimeout: 2000,
},
pingInterval: 5 * 60 * 1000, //Ping Each 5min. https://learn.microsoft.com/en-us/azure/azure-cache-for-redis/cache-best-practices-connection#idle-timeout
};
The application(nest.js) is hosted on render, and this error is often reported. Redis uses the vercel kv service.
CacheModule.registerAsync({
isGlobal: true,
useFactory: async () => {
const store = await redisStore({
socket: {
host: process.env.KV_HOST,
port: +process.env.KV_PORT,
tls: true,
},
username: process.env.KV_USERNAME,
password: process.env.KV_PASSWORD,
ttl: 60,
})
return {
store: store as unknown as CacheStore,
}
},
}),
ThrottlerModule.forRootAsync({
useFactory: () => ({
throttlers: [{ limit: 10, ttl: seconds(60) }],
storage: new ThrottlerStorageRedisService({
host: process.env.KV_HOST,
port: +process.env.KV_PORT,
username: process.env.KV_USERNAME,
password: process.env.KV_PASSWORD,
tls: true,
maxRetriesPerRequest: 20,
} as unknown as RedisOptions),
}),
}),
node:events:495
throw er; // Unhandled 'error' event
^
SocketClosedUnexpectedlyError: Socket closed unexpectedly
at TLSSocket.<anonymous> (/opt/render/project/src/node/node_modules/.pnpm/@redis+client@1.5.14/node_modules/@redis/client/dist/lib/client/socket.js:194:118)
at Object.onceWrapper (node:events:632:26)
at TLSSocket.emit (node:events:529:35)
at node:net:350:12
at TCP.done (node:_tls_wrap:657:7)
Emitted 'error' event on Commander instance at:
at RedisSocket.<anonymous> (/opt/render/project/src/node/node_modules/.pnpm/@redis+client@1.5.14/node_modules/@redis/client/dist/lib/client/index.js:412:14)
==> Requesting node version 18
==> Using Node version 18.19.1 via /opt/render/project/src/node/.nvmrc
==> Docs on specifying a Node version: https://render.com/docs/node-version
==> Running 'pnpm start'
> homing-pigeon-workspace@ start /opt/render/project/src/node
> pnpm --filter server start
> server@1.0.0 start /opt/render/project/src/node/server
> cross-env NODE_ENV=production node dist/main
at RedisSocket.emit (node:events:517:28)
at RedisSocket._RedisSocket_onSocketError (/opt/render/project/src/node/node_modules/.pnpm/@redis+client@1.5.14/node_modules/@redis/client/dist/lib/client/socket.js:218:10)
at TLSSocket.<anonymous> (/opt/render/project/src/node/node_modules/.pnpm/@redis+client@1.5.14/node_modules/@redis/client/dist/lib/client/socket.js:194:107)
at Object.onceWrapper (node:events:632:26)
[... lines matching original stack trace ...]
at TCP.done (node:_tls_wrap:657:7)
Node.js v18.19.1
/opt/render/project/src/node/server:
ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL server@1.0.0 start: `cross-env NODE_ENV=production node dist/main`
Exit status 1
ELIFECYCLE Command failed with exit code 1.
EDIT
node:events:495
throw er; // Unhandled 'error' event
^
SocketClosedUnexpectedlyError: Socket closed unexpectedly
at TLSSocket.<anonymous> (/opt/render/project/src/node_modules/.pnpm/@redis+client@1.5.16/node_modules/@redis/client/dist/lib/client/socket.js:194:118)
at Object.onceWrapper (node:events:632:26)
at TLSSocket.emit (node:events:529:35)
at node:net:350:12
at TCP.done (node:_tls_wrap:657:7)
Emitted 'error' event on Commander instance at:
at RedisSocket.<anonymous> (/opt/render/project/src/node_modules/.pnpm/@redis+client@1.5.16/node_modules/@redis/client/dist/lib/client/index.js:412:14)
at RedisSocket.emit (node:events:517:28)
at RedisSocket._RedisSocket_onSocketError (/opt/render/project/src/node_modules/.pnpm/@redis+client@1.5.16/node_modules/@redis/client/dist/lib/client/socket.js:218:10)
at TLSSocket.<anonymous> (/opt/render/project/src/node_modules/.pnpm/@redis+client@1.5.16/node_modules/@redis/client/dist/lib/client/socket.js:194:107)
at Object.onceWrapper (node:events:632:26)
[... lines matching original stack trace ...]
at TCP.done (node:_tls_wrap:657:7)
I am using docker to run Redis and as client, I am using node-redis. when I am executing my code I am getting
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
below is my code
import { createClient } from "redis";
const client = await createClient({
socket: {
host: "127.0.0.1",
port: 6379,
legacyMode: true,
},
})
.on('error', err => console.log('Redis Client Error', err))
await client.connect().catch(console.error);
console.log('redis connected...')
what is wrong in the code and how should we fix it ?
I've been having the same/similar issue. In my case I'm using createCluster()
.
The symptoms are that after a few minutes, Node.js will predictably crash with an unhandled SocketClosedUnexpectedlyError
, even though we have a listener on the 'error'
event.
Interestingly, the crashes are occasionally V8 heap-allocation-related, rather than an uncaught exception. So something weird definitely seems to be happening on the socket-close condition. Could it possibly be an infinite recursive loop trying to reconnect?
At first, nothing I tried seemed to fix the issue, until I changed the client idle timeout setting from 300
to 0
, effectively disabling it. Suddenly the crashing went away.
I am using docker to run Redis and as client, I am using node-redis. when I am executing my code I am getting
Redis Client Error SocketClosedUnexpectedlyError: Socket closed unexpectedly
below is my codeimport { createClient } from "redis"; const client = await createClient({ socket: { host: "127.0.0.1", port: 6379, legacyMode: true, }, }) .on('error', err => console.log('Redis Client Error', err)) await client.connect().catch(console.error); console.log('redis connected...')
what is wrong in the code and how should we fix it ?
FIX : I was using bitnami redis docker image later I used redis docker image after that I didn't see the above error.
The application(nest.js) is hosted on render, and this error is often reported. Redis uses the vercel kv service.
CacheModule.registerAsync({ isGlobal: true, useFactory: async () => { const store = await redisStore({ socket: { host: process.env.KV_HOST, port: +process.env.KV_PORT, tls: true, }, username: process.env.KV_USERNAME, password: process.env.KV_PASSWORD, ttl: 60, }) return { store: store as unknown as CacheStore, } }, }), ThrottlerModule.forRootAsync({ useFactory: () => ({ throttlers: [{ limit: 10, ttl: seconds(60) }], storage: new ThrottlerStorageRedisService({ host: process.env.KV_HOST, port: +process.env.KV_PORT, username: process.env.KV_USERNAME, password: process.env.KV_PASSWORD, tls: true, maxRetriesPerRequest: 20, } as unknown as RedisOptions), }), }),
node:events:495 throw er; // Unhandled 'error' event ^ SocketClosedUnexpectedlyError: Socket closed unexpectedly at TLSSocket.<anonymous> (/opt/render/project/src/node/node_modules/.pnpm/@redis+client@1.5.14/node_modules/@redis/client/dist/lib/client/socket.js:194:118) at Object.onceWrapper (node:events:632:26) at TLSSocket.emit (node:events:529:35) at node:net:350:12 at TCP.done (node:_tls_wrap:657:7) Emitted 'error' event on Commander instance at: at RedisSocket.<anonymous> (/opt/render/project/src/node/node_modules/.pnpm/@redis+client@1.5.14/node_modules/@redis/client/dist/lib/client/index.js:412:14) ==> Requesting node version 18 ==> Using Node version 18.19.1 via /opt/render/project/src/node/.nvmrc ==> Docs on specifying a Node version: https://render.com/docs/node-version ==> Running 'pnpm start' > homing-pigeon-workspace@ start /opt/render/project/src/node > pnpm --filter server start > server@1.0.0 start /opt/render/project/src/node/server > cross-env NODE_ENV=production node dist/main at RedisSocket.emit (node:events:517:28) at RedisSocket._RedisSocket_onSocketError (/opt/render/project/src/node/node_modules/.pnpm/@redis+client@1.5.14/node_modules/@redis/client/dist/lib/client/socket.js:218:10) at TLSSocket.<anonymous> (/opt/render/project/src/node/node_modules/.pnpm/@redis+client@1.5.14/node_modules/@redis/client/dist/lib/client/socket.js:194:107) at Object.onceWrapper (node:events:632:26) [... lines matching original stack trace ...] at TCP.done (node:_tls_wrap:657:7) Node.js v18.19.1 /opt/render/project/src/node/server: ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL server@1.0.0 start: `cross-env NODE_ENV=production node dist/main` Exit status 1 ELIFECYCLE Command failed with exit code 1.
EDIT
node:events:495 throw er; // Unhandled 'error' event ^ SocketClosedUnexpectedlyError: Socket closed unexpectedly at TLSSocket.<anonymous> (/opt/render/project/src/node_modules/.pnpm/@redis+client@1.5.16/node_modules/@redis/client/dist/lib/client/socket.js:194:118) at Object.onceWrapper (node:events:632:26) at TLSSocket.emit (node:events:529:35) at node:net:350:12 at TCP.done (node:_tls_wrap:657:7) Emitted 'error' event on Commander instance at: at RedisSocket.<anonymous> (/opt/render/project/src/node_modules/.pnpm/@redis+client@1.5.16/node_modules/@redis/client/dist/lib/client/index.js:412:14) at RedisSocket.emit (node:events:517:28) at RedisSocket._RedisSocket_onSocketError (/opt/render/project/src/node_modules/.pnpm/@redis+client@1.5.16/node_modules/@redis/client/dist/lib/client/socket.js:218:10) at TLSSocket.<anonymous> (/opt/render/project/src/node_modules/.pnpm/@redis+client@1.5.16/node_modules/@redis/client/dist/lib/client/socket.js:194:107) at Object.onceWrapper (node:events:632:26) [... lines matching original stack trace ...] at TCP.done (node:_tls_wrap:657:7)
I'm having the same issue
How to fix this?
If its like my solution, double check you are not trying to set or get while the connection is down. Add a global variable for yourself to check that updates
let alive=false _redisClient.on('end', () => { alive=false }); _redisClient.on('ready', () => { alive=true }); _redisClient.on('error', (err) => { alive=false });
and before redisClient.set()
if (alive){ redisClient.set(etc, etc2) }
That way you don't try to set when its dead. I made a whole wrapper class around redis so it was trivial to add a check to all of them
Hello @TDola
I implemented my redisClient class this way as you suggested. Here is the class definition.
class Client {
alive: boolean;
client: RedisClientType;
constructor() {
this.alive = false;
this.client = createClient({
username: process.env.REDIS_USERNAME,
password: process.env.REDIS_PASSWORD,
socket: {
host: process.env.REDIS_HOST,
port: Number(process.env.REDIS_PORT),
tls: true,
},
});
this.createConnection();
}
createConnection = () => {
try {
this.client
.on("error", (err: any) => {
this.alive = false;
console.error("Redis error", err);
})
.on("ready", () => {
this.alive = true;
console.log("Client is ready");
})
.on("end", () => {
this.alive = false;
console.log("Client ended");
})
.connect();
} catch (err: any) {
console.error("Error occured during creating client", err);
} finally {
// await redisClient.disconnect();
}
};
hSet = async (key: RedisCommandArgument, value: any) => {
if (this.alive) {
return await this.client.hSet(key, value);
}
};
hGet = async (key: RedisCommandArgument, field: string) => {
if (this.alive) {
return await this.client.hGet(key, field);
}
};
hGetAll = async (key: RedisCommandArgument) => {
if (this.alive) {
return await this.client.hGetAll(key);
}
};
exists = async (key: RedisCommandArgument) => {
if (this.alive) {
return await this.client.exists(key);
}
};
hIncrBy = async (key: RedisCommandArgument, field: string, value: number) => {
if (this.alive) {
return await this.client.hIncrBy(key, field, value);
}
};
}
export default new Client();
But this keeps the "Socket unexpectedly closed" error and also introduces a new error saying "cannot read properties of undefined (reading hSet)" which I think indicates that my client is undefined at a point of time. Am I doing something wrong? Any suggestions will be helpful. Thanks in advance.
How to fix this?
If its like my solution, double check you are not trying to set or get while the connection is down. Add a global variable for yourself to check that updates
let alive=false _redisClient.on('end', () => { alive=false }); _redisClient.on('ready', () => { alive=true }); _redisClient.on('error', (err) => { alive=false });
and before redisClient.set()
if (alive){ redisClient.set(etc, etc2) }
That way you don't try to set when its dead. I made a whole wrapper class around redis so it was trivial to add a check to all of them
Hello @TDola
I implemented my redisClient class this way as you suggested. Here is the class definition.
class Client { alive: boolean; client: RedisClientType; constructor() { this.alive = false; this.client = createClient({ username: process.env.REDIS_USERNAME, password: process.env.REDIS_PASSWORD, socket: { host: process.env.REDIS_HOST, port: Number(process.env.REDIS_PORT), tls: true, }, }); this.createConnection(); } createConnection = () => { try { this.client .on("error", (err: any) => { this.alive = false; console.error("Redis error", err); }) .on("ready", () => { this.alive = true; console.log("Client is ready"); }) .on("end", () => { this.alive = false; console.log("Client ended"); }) .connect(); } catch (err: any) { console.error("Error occured during creating client", err); } finally { // await redisClient.disconnect(); } }; hSet = async (key: RedisCommandArgument, value: any) => { if (this.alive) { return await this.client.hSet(key, value); } }; hGet = async (key: RedisCommandArgument, field: string) => { if (this.alive) { return await this.client.hGet(key, field); } }; hGetAll = async (key: RedisCommandArgument) => { if (this.alive) { return await this.client.hGetAll(key); } }; exists = async (key: RedisCommandArgument) => { if (this.alive) { return await this.client.exists(key); } }; hIncrBy = async (key: RedisCommandArgument, field: string, value: number) => { if (this.alive) { return await this.client.hIncrBy(key, field, value); } }; } export default new Client();
But this keeps the "Socket unexpectedly closed" error and also introduces a new error saying "cannot read properties of undefined (reading hSet)" which I think indicates that my client is undefined at a point of time. Am I doing something wrong? Any suggestions will be helpful. Thanks in advance.
What you have looks pretty much the same as how I implemented it. So it might be just when you are calling it. If you are accidentally calling your sets before you have time to construct your class and wait for the connect to finish.
Also, the catches were unexpectedly important, as shown in the response to my question here https://github.com/redis/node-redis/issues/2624#issuecomment-1770996791
Description
Hi,
We are experiencing issue with the client. Many times a day we have this unhandled error that is thrown away from the redis client.
We have properly set the "Error" handler but it is not catched in it. As a consequence our process is crashing multiple times per day. It is severly impacting our customers.
We already dig into the issue list where this error was mentionned, we tried the PingInterval / SetInterval stuff as we are on Azure but it doesn't fix the issue.
I suspect this is another edge case than the load balancer that drop the connection. If you can see how to catch properly this error so the reconnect system can reopen smoothlty the connection it will save our day.
Thanks,
Node.js Version
Node.js v18.17.1
Redis Server Version
Node.js v18.17.1
Node Redis Version
No response
Platform
Linux
Logs