Skip to content

WSClient (long connection) silently drops im.message.receive_v1 events under load — no dispatch, no log, no disconnect #201

Description

@Noah0025

Environment

  • @larksuiteoapi/node-sdk: 1.71.1 (also reproduced on 1.70.0)
  • Runtime: Bun 1.3.x / Node-compatible, macOS
  • Mode: WSClient long connection (new WSClient({ appId, appSecret, domain: Domain.Feishu }).start({ eventDispatcher }))
  • Event subscribed: im.message.receive_v1 via new EventDispatcher({}).register({ 'im.message.receive_v1': handler })
  • domain: Feishu (open.feishu.cn), self-built app

Summary

Under load — when several im.message.receive_v1 events arrive in close succession while the app is busy handling a previous event (e.g. making outbound im/v1/messages API calls to reply) — the WSClient occasionally drops an event entirely:

  • The Feishu event delivery log (Developer Console → 事件与回调 / event log) shows the event was pushed with success / httpCode: 200 / hookType: 4 (long connection). So Feishu delivered it and the transport ACKed it.
  • But the registered im.message.receive_v1 handler is never invoked for that event.
  • Even with loggerLevel set to debug, the SDK's own [ws] "receive message, message_type: event; message_id: ..." debug line does not appear for the dropped event.
  • No disconnect / error event is emitted, so application-level health checks based on reconnection never trigger.

The event is acknowledged at the transport layer but lost before reaching the dispatcher/handler.

Impact

For a chat bot on long connection, this means user messages are silently not processed (no reply) with no error surfaced anywhere in the SDK. Observed drop rate rises sharply when messages arrive while the app is mid-processing a previous one.

Reproduction (observed)

  1. Long-connection WSClient with a single im.message.receive_v1 handler that does non-trivial async work (streaming reply via multiple PUT im/v1/messages/{id} edits).
  2. Send several messages to the bot in quick succession (so a new event arrives while the previous is still being handled / while outbound API calls are in flight).
  3. Compare:
    • Feishu Console event log: N events, all SUCCESS.
    • SDK debug log [ws] receive message lines: fewer than N.
    • Handler invocations: match the SDK debug count, i.e. the missing events never reach the handler.

Concrete instance (message ids redacted): Feishu pushed 6 im.message.receive_v1 events (all SUCCESS in the console within ~20s); the SDK produced only 3 [ws] receive message debug lines; the other 3 were never dispatched and never logged. No disconnect fired; the connection kept working for subsequent events.

Expected

Every event Feishu delivers + ACKs over the long connection should either be dispatched to the registered handler, or — if it cannot be — surfaced as an error/warn log or a recoverable event, so the application can react (e.g. reconcile). Silent loss with a transport-level SUCCESS is the worst case.

Questions

  • Is there internal back-pressure / a bounded queue in the WSClient receive path that drops frames when the handler is slow or the event loop is busy?
  • Is there a recommended way to detect or reconcile dropped long-connection events (short of periodically polling im/v1/messages)?

Workaround currently in use

Periodic reconciliation: on activity, poll GET /im/v1/messages for active chats and re-feed any message not yet processed (dedup by message_id). This recovers dropped messages but shouldn't be necessary.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions