Skip to content

Contact fetch with extraProperties=avatar blocks the Node event loop ~5s, causing client disconnect/reconnect loops ("connecting") #811

@johndkos

Description

@johndkos

Environment

  • Server: 1.9.9 (latest stable)
  • macOS: 15.7.7 (build 24G720)
  • Messages: 14.0
  • Private API: enabled, mode process-dylib, helper connected (helper_connected: true)
  • ~2,500 contacts, served live from the macOS Contacts framework (the server's own contact DB table is empty)

Summary

GET /api/v1/contact?extraProperties=avatar takes ~4.3–5.7s and blocks the Node event loop for its duration. Clients re-request contacts-with-avatars on every (re)connect; because the block exceeds the client's ~5s reachability-probe window, the client tears down the socket (client namespace disconnect) and reconnects, which re-triggers the fetch. The result is a repeating loop that surfaces on clients as being stuck on "connecting."

Reproduction (measured on the server itself, bypassing any tunnel)

Idle GET /api/v1/ping ≈ 0.002s. Fire GET /api/v1/contact?extraProperties=avatar in the background and ping repeatedly during it:

ping #1 (during avatar fetch): 4.83s
ping #2–9 (after the synchronous phase): ~0.002s each

A single ~5s synchronous block, not a gradual slowdown. For comparison, on the same server:

  • GET /api/v1/contact (no avatars): ~6–25ms
  • GET /api/v1/server/statistics/totals: ~3ms

Only the avatar variant blocks.

Server log pattern (redacted)

Request to /api/v1/contact (URL Params: {"extraProperties":"avatar"})
Request to /api/v1/contact took 5313 ms
[SocketRoutes] Client <id> disconnected! Reason: client namespace disconnect
Request to /api/v1/contact (URL Params: {"extraProperties":"avatar"})
Request to /api/v1/contact took 5455 ms
[SocketRoutes] Client <id> disconnected! Reason: client namespace disconnect

(repeating every ~15–30s)

Suspected cause

Synchronous avatar loading from the macOS Contacts framework (node-mac-contacts) on the main thread; cost scales with contact count. At ~2,500 contacts the block sits right around the client's ~5s probe timeout, which makes the disconnects intermittent.

Impact

Clients (Windows desktop observed) repeatedly drop to "connecting"; each reconnect re-triggers the blocking fetch.

Possible fixes

  • Load avatars off the main thread (worker), or stream/paginate, or cache avatars server-side so the request is a fast read rather than a live Contacts-framework call.
  • Is this already addressed by the contacts API work in Contacts API Improvements #701 / the development branch? If so, would a stable release resolve it (cf. macOS 15 Server Update 2.0.0? #700 re: a macOS 15 / 2.0.0 release)?

A fuller redacted server log (last ~3h) is available if helpful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions