Updated:
Tested on: macOS 26 and 27.0, Korg Keystage and opsix module connected by USB

We connected a Korg Keystage and an opsix module to a Mac by USB, routed them to each other in MIDIFabric, and MIDI-CI Property Exchange would not work.

We suspect that macOS relaying MIDI-CI messages overlaps with the app’s routing, causing duplicate messages. Property Exchange failed to connect or stopped working after a device was power-cycled. We have not established the exact cause. Connecting the two devices directly with MIDI (DIN) cables worked.

How we noticed

In a MIDI monitor, the device we had power-cycled kept sending MIDI-CI Discovery about every 100 ms, and each time the other device answered with “Invalidate MUID”. A connection that had worked once never came back after the power cycle.

To find out whether MIDIFabric’s routing was to blame, we stopped MIDIFabric and watched with only a MIDI monitor running. That showed us that macOS itself takes part in MIDI-CI and relays messages between the devices.

What you might see

  • A controller does not show the parameter names of a synth that supports Property Exchange.
  • It worked once, but after you power-cycled one device it never connects again.
  • A MIDI monitor shows the same MIDI-CI Discovery messages repeating about every 100 ms, each followed by “Invalidate MUID”.

What macOS does with MIDI-CI

These are things we confirmed with a MIDI monitor, with no routing app running:

  • macOS takes part in MIDI-CI itself. MIDIServer sends its own Discovery to USB devices, with a new MUID each time it starts, and asks them for Property Exchange information (PE Capabilities and the ResourceList). Apple’s CoreMIDI documentation says the MIDI server runs MIDI-CI discovery automatically for UMP endpoints and MIDI 1.0 devices.
  • macOS relays some broadcast MIDI-CI messages between devices. A Discovery that the opsix module sent to all devices was delivered to the Keystage by MIDIServer itself. We saw this in the opsix → Keystage direction only, not the other way. Messages addressed to one specific device were usually not relayed, but we cannot rule it out.
  • The number of relays changes. Right after MIDIServer started, the message was relayed once. On another day we saw three. After the devices had repeatedly reconnected, one message from the opsix module made the Keystage reply hundreds of times.

Possible involvement of duplicate messages

MIDI-CI requires messages in both directions. If macOS relays a broadcast message that the routing app also forwards, the destination receives it twice and can reply twice. We suspect these duplicate replies are involved in the MUID conflicts and the repeated Discovery / Invalidate MUID sequence we observed.

The device side may also play a part: we saw a device invalidate the new MUID of a device it had seen before. We have not separated these causes.

There are limits to an app-side workaround. macOS offers no public setting to stop its own MIDI-CI discovery or relaying (MIDICIDeviceManager only reports discovered devices). In MIDIFabric we tried removing duplicate MIDI-CI messages along the route, but the direction and number of relays were not constant, and it also removed duplicates the devices sent on purpose, so we did not adopt it.

What you can do

  1. Connect the two devices directly with MIDI (DIN) cables for MIDI-CI between them. In our test, MIDI-CI worked this way as long as the device we power-cycled was not connected to the Mac by USB.
  2. Reset after repeated Discovery / Invalidate MUID messages. Quit every app that uses MIDI so that MIDIServer quits, then power-cycle the devices.
  3. Block SysEx on routes that do not need MIDI-CI. If you only need notes and controllers between the devices, filter out SysEx on that route. MIDI-CI messages are SysEx, so this stops the loop, but Property Exchange will not work over that route.

About MIDIFabric

MIDIFabric forwards MIDI-CI unchanged, and its monitor shows MIDI-CI messages by name. The relaying described above is done by macOS and also happens without MIDIFabric.

← All developer notes