Skip to content

TDLib client closes after successful login and keepOnline crashes the server #141

Description

@shafed

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:

  1. Run :Tg, or start the backend manually:

    cd ~/.local/share/nvim/lazy/telegram.nvim
    npx tsx src/server.ts
  2. Complete Telegram authentication (phone number, code, and 2FA password if required).

  3. Verify that the backend reports:

    TDLib client ready
    

    and:

    curl -s http://localhost:8080/health | jq

    returns:

    {
      "ready": true,
      "auth": {
        "state": "ready",
        "error": null,
        "canInput": false
      }
    }
  4. Wait for the keepOnline timer to run.

  5. 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)
    
  6. 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions