Skip to content

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

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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions