#678

Remote Monitor: layout placement survives unpair/re-pair and leaves a stale rule keyed to a dead client UUID

OpenVapor-Nexusopened 12d ago

Version: Vibepollo 2.0.1 (commit 66e169c), Windows 11 25H2 (build 26200), RTX 5090, bundled Sunshine virtual display driver Client: Steam Deck (Moonlight), added as a Remote Monitor

Summary

When a client that has a Remote Monitor layout placement is unpaired and paired again, it gets a new client UUID, but its old placement stays in remote_display_layout keyed to the old UUID. The new client has no placement, and the stale entry is never cleaned up. It is not visible in the Display Layout page either, because that client no longer exists in the client list, so there is no UI way to remove it.

I hit this while debugging a Remote Monitor that always failed with 503 on connect (details below). I am not certain the stale rule caused the 503 by itself, but it was clearly left-behind state, and I had to hand-clean it through the API.

Steps to reproduce

  1. Pair a client and add it as a Remote Monitor.
  2. On the Display Layout page, give it a placement (e.g. "below" another client, centered, 10 px gap). Save.
  3. Unpair that client (POST /api/clients/unpair).
  4. Pair the same device again. It receives a new UUID.
  5. GET /api/clients/display-layout (or open sunshine_state.json).

Expected

Unpairing removes the client's placement from remote_display_layout, or the placement is migrated/ignored and surfaced somewhere it can be deleted.

Actual

layout.placements still contains an entry keyed to the old UUID, with anchor_kind: client pointing at another client. The new UUID has no entry. The old UUID does not appear in clients[], so the Display Layout page shows nothing to remove.

"layout": {
  "placements": {
    "<OLD-CLIENT-UUID>": {
      "alignment": "center",
      "anchor_id": "<ANCHOR-CLIENT-UUID>",
      "anchor_kind": "client",
      "edge": "below",
      "gap_px": 10,
      "preserve": false,
      "primary": false
    }
  },
  "version": 1
}

Where it comes from (from reading the source)

  • remote_display_topology::coordinator_t::unpair_client() only calls disconnect_monitor(client_uuid). It never touches layout_["placements"].
  • compose_locked() looks up placements by the current client UUID, so after re-pair the new client falls through to the "appended to the right" default, and the stale entry just sits there forever.

Context: the 503 this was tangled up with

While the stale rule existed, every Remote Monitor connect from this client failed with a topology/layout 503. In the log, the virtual display was created fine, then:

Display helper: requested topology already active (remote-monitor coordinator).
Display helper: setting origin for {<device>} to (3840,0) after remote-monitor coordinator.
Warning: [code: ERROR_ACCESS_DENIED, message: Access is denied] while executing initial setDisplayConfig validation.
Error: [code: ERROR_ACCESS_DENIED, message: Access is denied] failed to move device {<device>} to new origin!
Warning: Display helper: failed to set origin for {<device>} (remote-monitor coordinator).

All SetDisplayConfig calls on the Remote Monitor path failed this way (76 in one log), on dd_display_helper_engine = legacy (the default on stable builds).

What fixed it, done together:

  1. Cleared the stale placement with PUT /api/clients/display-layout and body {"placements":{},"version":1} (Vibepollo running).
  2. Set dd_display_helper_engine to v2 and restarted Vibepollo.

After that the Remote Monitor connected on the first try and has been stable since. The ERROR_ACCESS_DENIED lines are gone. Other non-default settings at the time: dd_use_sunshine_virtual_display_driver = enabled, virtual_display_max_clients = 8, dd_hdr_request_override = force_on.

Asks

  1. Remove a client's remote_display_layout placement on unpair (or on re-pair with a new UUID).
  2. Have the Display Layout page show or prune placements whose UUID is not in the client list, so they can be deleted without editing state by hand.
  3. Optional: if the legacy engine's in-process origin move is expected to hit ERROR_ACCESS_DENIED when sunshine.exe runs as SYSTEM, consider routing the Remote Monitor origin apply through the helper on legacy too, or defaulting Remote Monitor users to v2.

Activity

0

No activity yet.