WebSocket XMR "Invalid key" for ALL client types on single-instance CMS 4.5 (Queue::authKey never populated via addKey)

After upgrading our CMS from 4.4.3 to 4.5.0 (custom/manual installation, not the Docker image), our players’ XMR WebSocket connections started closing almost immediately after connecting, repeatedly. This affects any client type – confirmed identically with both a third-party Linux player (arexibo) and the official Windows player.

On the XMR relay’s own log:

[2026-08-10 14:30:55] xmr.ERROR: onMessage: Invalid key [] []

repeating on the same cadence as each player’s reconnect attempts, regardless of which client connects.

Traced this to src/Controller/Server.php’s onMessage():

php

if (!$this->queue->authKey($key)) {
    throw new \InvalidArgumentException('Invalid key');
}

Queue::authKey() only returns true if a matching key was previously registered via Queue::addKey($instance, $key), which (per src/Controller/Api.php) only happens when the CMS itself POSTs {"type":"keys","id":...,"key":...} to the relay’s private API address.

Verified before reporting, to rule out a configuration issue on our end:

  • XMR Private Address in CMS settings (http://localhost:8081) matches the relay’s own config.json ("api": "0.0.0.0:8081").
  • Confirmed the endpoint is reachable and functioning correctly from the CMS server itself:
  curl -X POST http://localhost:8081 -d '{"type":"stats"}'
  → 200 OK, valid JSON stats response
  • This rules out a network/address misconfiguration; the CMS should be able to reach the relay’s API without issue.

Given connectivity is confirmed working, it appears the CMS-side code that’s supposed to call this "keys" endpoint (to register a valid key for a display’s channel) is either never triggered, or not wired up for a standard single-instance CMS deployment – authKey() always returns false regardless of what key any player sends, for any client type.

Question: is there a CMS-side code path that’s supposed to call the relay’s "keys" API endpoint proactively (e.g. during RegisterDisplay, on a schedule, or on CMS startup) that might be missing or not firing for a standard single-instance deployment? Given Relay/isRelay()/isRelayOld() in index.php suggest this key mechanism may be designed primarily for a multi-instance relay scenario, we suspect this registration call may simply never happen in a standard setup.

(Side note, possibly unrelated: our XMR Public Address is currently set to ws://<ip>:9505, but port 9505 in config.json is configured for ZMQ ("zmq": ["tcp://*:9505"]), not WebSocket – this looks like it should be tcp:// for the legacy ZMQ fallback address, not ws://. Flagging this in case it’s relevant, though we don’t believe it’s the cause of the “Invalid key” issue specifically.)

Happy to provide more logs/detail if useful.

Check out my post about installing 4.5.0. Install Xibo on Debian | Sifr Moja

I have tested this with multiple clients and it is all working.

Thanks already fixed with public IP address…

Hello,

Same issue here, confirmed on CMS 4.5.1 (manual install, Ubuntu 24.04, Apache 2.4.58,
PHP 8.4, MariaDB 11.7), upgraded from 4.4.4. Went through a full diagnostic pass and
wanted to share the results in case they help narrow this down.

Confirmed working (ruled out):

  • XMR relay itself: running fine as a systemd service, ws/api/zmq sockets all bind
    and listen correctly (confirmed via ss -tlnp and debug-mode logs)
  • WebSocket path (both via Apache mod_proxy_wstunnel on /xmr, and later tested
    with a direct connection to the relay’s :8080): confirmed working, upgrade
    handshake returns 101 Switching Protocols
  • XMR’s private API endpoint: fully functional when tested directly —
    curl -X POST http://<ip>:8081 -d '{"type":"stats"}' -H "Content-Type: application/json"
    returns a valid stats JSON response every time
  • DB settings (XMR_ADDRESS, XMR_PUB_ADDRESS, XMR_WS_ADDRESS in the setting
    table): all consistent with what the Settings UI shows, no stale/leftover values
    from the 4.4→4.5 upgrade

Still broken:

  • xmr.ERROR: onMessage: Missing key repeating continuously, exact same symptom
    as OP, regardless of client
  • Tried every address/scheme combination I could think of for “XMR Private Address”:
    tcp://127.0.0.1:8081, tcp://<server-ip>:8081, http://127.0.0.1:8081,
    http://<server-ip>:8081, http://localhost:8081 — no change in behaviour with any of them
  • Tried the “Reconfiguration du XMR” checkbox on an individual Display’s edit page
    (regenerates the hardware key) — no new activity appears in the XMR log at all
    when saving, even with debug logging enabled on the relay
  • Mirrored an entire working config from another manual 4.5.0 install I found
    (0.0.0.0 binding for ws/api instead of a specific interface, direct WebSocket
    connection to :8080 bypassing the reverse proxy entirely) — identical result,
    still “Missing key”
  • Checked Apache’s error.log for any suppressed exception (Guzzle connection
    error, timeout, etc.) around the moment of triggering a key push — completely
    empty, no trace whatsoever

Conclusion: nowhere — not in the CMS’s own log table, not in Apache’s error
log, not in XMR’s own log — is there any evidence the CMS ever attempts to call
XMR’s key-registration endpoint. Every component downstream of that call (the
relay itself, the network path, the private API) is confirmed fully functional
when tested directly and independently. This strongly supports your hypothesis
that the code path meant to invoke this call (addKey/isRelay()) is simply
never wired up for a standard single-instance manual install on 4.5.x.

Not blocking for us since XMDS/polling still delivers layouts and schedules
normally — just no more instant push notifications. Parking this for now, but
happy to provide a tcpdump on :8081 during a key-regeneration attempt, or any
other server-side diagnostic, if a maintainer wants to dig further.

tcp://serveraddr:8081works for me but be sure that in the firewall you accept connections at least from your host also be sure that in the xmr config.json you have 0.0.0.0:8081 as listen address..

It really takes a lot before xtr perform initial registration but after 3 or 4 minutes everything seems ok…

registration of the cms on xmr is done during regular maintenance, by default is a task performed every 5 minutes, be sure to have xtr task configured in cron.

I aslo had issues. We use a proxy for internet connection and I had to exclude cms-xmr from the proxy (exclusion list) to get it working.