-
Notifications
You must be signed in to change notification settings - Fork 207
Description
I am encountering a critical issue with @binance/spot version ^26.0.0. When the internet connection is lost while a user stream (WebSocket API) is running, the application crashes due to an unhandled 'error' event.
Unlike version v20.0.1, where the connection would attempt to reconnect or allow the error to be caught, the current version throws an unhandled exception effectively killing the Node.js process.
Environment
Package version: @binance/spot ^26.0.0
Node.js version: v24.11.1
OS: Windows 11
Steps to Reproduce
Initialize the Spot client.
Start a WebSocket connection (e.g., user stream).
Disconnect the internet connection (simulate network loss).
The application crashes with Error: getaddrinfo ENOTFOUND.
Actual Behavior
The application crashes immediately. The internal reconnection logic does not seem to trigger, and I am unable to catch the error in my application code because it is thrown as an unhandled event.
Expected Behavior
The library should either:
Handle the error internally and trigger the auto-reconnect logic (as observed in v20.0.1).
Or emit the error in a way that can be caught by the user without crashing the process.
Error Log
[2025-12-10T12:16:11.266Z] [info] Establishing Websocket connection with id a41db9caba555627e627b4ce2e0fb829 to: wss://ws-api.testnet.binance.vision/ws-api/v3
[2025-12-10T12:16:11.268Z] [error] Received error from server
[2025-12-10T12:16:11.271Z] [error] Error: getaddrinfo ENOTFOUND ws-api.testnet.binance.vision
at GetAddrInfoReqWrap.onlookupall [as oncomplete] (node:dns:122:26) {
errno: -3008,
code: 'ENOTFOUND',
syscall: 'getaddrinfo',
hostname: 'ws-api.testnet.binance.vision'
}
node:events:486
throw er; // Unhandled 'error' event
^
Error: getaddrinfo ENOTFOUND ws-api.testnet.binance.vision
at GetAddrInfoReqWrap.onlookupall [as oncomplete] (node:dns:122:26)
Emitted 'error' event at:
at WebsocketAPIBase.emit (...\node_modules\@binance\common\src\websocket.ts:44:27)
at WebSocket.<anonymous> (...\node_modules\@binance\common\src\websocket.ts:546:18)
at WebSocket.emit (node:events:520:35)
at emitErrorAndClose (...\node_modules\ws\lib\websocket.js:1041:13)
at ClientRequest.<anonymous> (...\node_modules\ws\lib\websocket.js:881:5)
at ClientRequest.emit (node:events:508:28)
at emitErrorEvent (node:_http_client:108:11)
at TLSSocket.socketErrorListener (node:_http_client:575:5)
at TLSSocket.emit (node:events:508:28)
at emitErrorNT (node:internal/streams/destroy:170:8) {
errno: -3008,
code: 'ENOTFOUND',
syscall: 'getaddrinfo',
hostname: 'ws-api.testnet.binance.vision'
}
Node.js v24.11.1
error: script "dev:server" exited with code 1
Possible Cause & Location
Looking at the stack trace, the issue seems to originate in @binance/common/src/websocket.ts#550
It appears that at line #546 (inside the error handler), the error is re-emitted. However, if the reconnection logicfails or doesn't intercept this specific DNS error (ENOTFOUND), the error event propagates. Since there might be no listener attached to handle this specific emission sequence during the disconnect, Node.js throws the fatal error.
Code
private async initializeUserDataStream(): Promise<void> {
try {
this.userDataWs = await this.client.websocketAPI.connect();
console.log(`[Client:${this.sessionId}] User data stream connected`);
const { stream } = await this.userDataWs.userDataStreamSubscribeSignature();
console.log(`[Client:${this.sessionId}] User data stream Subscribed`);
this.startUserDataPingInterval();
stream.on('message', (data: any) => {
try {
this.handleUserDataMessage(data);
} catch (error: any) {
console.error(`[Client:${this.sessionId}] Error parsing user data message: ${error.message}`);
}
});
this.userDataWs.on('open', () => {
this.isReconnectingUserData = false;
console.log(`[Client:${this.sessionId}] User data stream connected`);
});
this.userDataWs.on('ping', (event: any) => {
console.error(`[Client:${this.sessionId}] User data WebSocket ping`);
});
this.userDataWs.on('error', (error: any) => {
console.error(`[Client:${this.sessionId}] User data WebSocket error`, error);
if (!this.isReconnectingUserData) {
this.reconnectUserDataStream();
}
});
this.userDataWs.on('close', (e: any) => {
console.log(`[Client:${this.sessionId}] connection closed`, e);
if (!this.isReconnectingUserData) {
this.reconnectUserDataStream();
}
});
} catch (error: any) {
console.error(`[Client:${this.sessionId}] Failed to initialize user data stream`, error);
throw error;
}
}