After successfully authenticating with Telegram, the backend reaches the ready state, but shortly afterwards the underlying tdl client becomes closed.
The keepOnline timer in src/client.ts still tries to call client.invoke(...) on the closed client, which crashes the Node.js server with:
Error: A closed client cannot be reused, create a new client
In my case, :Tg also reports that no chats were found before the backend eventually crashes.
To Reproduce
Steps to reproduce the behavior:
-
Run :Tg, or start the backend manually:
cd ~/.local/share/nvim/lazy/telegram.nvim
npx tsx src/server.ts
-
Complete Telegram authentication (phone number, code, and 2FA password if required).
-
Verify that the backend reports:
and:
curl -s http://localhost:8080/health | jq
returns:
{
"ready": true,
"auth": {
"state": "ready",
"error": null,
"canInput": false
}
}
-
Wait for the keepOnline timer to run.
-
The backend crashes with:
Error: A closed client cannot be reused, create a new client
at Client._send (.../node_modules/tdl/dist/client.js:481:19)
at Client.invoke (.../node_modules/tdl/dist/client.js:228:18)
at Timeout.keepOnline (.../src/client.ts:147:21)
-
When opening Telegram from Neovim, I also get No chats found.
Expected behavior
After successful authentication, the TDLib client should remain usable and :Tg should load the user's chats.
If the TDLib client is closed for some reason, the keepOnline timer should stop instead of calling invoke() on a closed client and crashing the backend.
Ideally, the backend should also log why the TDLib client was closed.
Screenshots / Logs
Backend startup:
TDLib library: /usr/lib/libtdjson.so.1.8.64
HTTP server: http://localhost:8080
WebSocket server: ws://localhost:8081
TDLib version: 1.8.64
After authentication:
{
"ready": true,
"auth": {
"state": "ready",
"hint": "",
"error": null,
"canInput": false
}
}
Some TDLib messages printed before the crash:
[AttachMenuManager] Have no colors for attachment menu bot icon
[AttachMenuManager] Have icon ... with name android_active_animated
[StickersManager] Trending sticker sets hash mismatch
Crash:
/home/shafed/.local/share/nvim/lazy/telegram.nvim/node_modules/tdl/dist/client.js:481
throw new Error('A closed client cannot be reused, create a new client');
^
Error: A closed client cannot be reused, create a new client
at Client._send (/home/shafed/.local/share/nvim/lazy/telegram.nvim/node_modules/tdl/dist/client.js:481:19)
at Client.invoke (/home/shafed/.local/share/nvim/lazy/telegram.nvim/node_modules/tdl/dist/client.js:228:18)
at Timeout.keepOnline (/home/shafed/.local/share/nvim/lazy/telegram.nvim/src/client.ts:147:21)
at listOnTimeout (node:internal/timers:685:17)
at process.processTimers (node:internal/timers:618:7)
Node.js v26.8.1
Environment (please complete):
- OS: Arch Linux
- Neovim version: 0.11.3
- Node.js version: 26.8.1
- TDLib version: 1.8.64
- telegram.nvim version: current
main
Additional context
The backend can successfully connect to TDLib and complete authentication. /health reports ready: true before the crash, so the failure happens after authentication.
The immediate crash appears to come from the keepOnline timer continuing to call:
this.client.invoke({
_: 'setOption',
name: 'online',
value: { _: 'optionValueBoolean', value: true }
})
after the underlying tdl client has already been closed.
It may be useful to listen for the client's close event, set _ready = false, cancel _keepOnlineTimer, and log the reason/state transition. This would prevent the secondary crash and make it easier to diagnose why the client is closing in the first place.
After successfully authenticating with Telegram, the backend reaches the
readystate, but shortly afterwards the underlyingtdlclient becomes closed.The
keepOnlinetimer insrc/client.tsstill tries to callclient.invoke(...)on the closed client, which crashes the Node.js server with:Error: A closed client cannot be reused, create a new clientIn my case,
:Tgalso reports that no chats were found before the backend eventually crashes.To Reproduce
Steps to reproduce the behavior:
Run
:Tg, or start the backend manually:Complete Telegram authentication (phone number, code, and 2FA password if required).
Verify that the backend reports:
and:
curl -s http://localhost:8080/health | jqreturns:
{ "ready": true, "auth": { "state": "ready", "error": null, "canInput": false } }Wait for the
keepOnlinetimer to run.The backend crashes with:
When opening Telegram from Neovim, I also get
No chats found.Expected behavior
After successful authentication, the TDLib client should remain usable and
:Tgshould load the user's chats.If the TDLib client is closed for some reason, the
keepOnlinetimer should stop instead of callinginvoke()on a closed client and crashing the backend.Ideally, the backend should also log why the TDLib client was closed.
Screenshots / Logs
Backend startup:
After authentication:
{ "ready": true, "auth": { "state": "ready", "hint": "", "error": null, "canInput": false } }Some TDLib messages printed before the crash:
Crash:
Environment (please complete):
mainAdditional context
The backend can successfully connect to TDLib and complete authentication.
/healthreportsready: truebefore the crash, so the failure happens after authentication.The immediate crash appears to come from the
keepOnlinetimer continuing to call:after the underlying
tdlclient has already been closed.It may be useful to listen for the client's
closeevent, set_ready = false, cancel_keepOnlineTimer, and log the reason/state transition. This would prevent the secondary crash and make it easier to diagnose why the client is closing in the first place.