Normal for Reaper I/O matrix to delete bus channels?

I am working on a multi-out drum synth, and have noticed that in Reaper when removing pins from my plugin’s I/O matrix, it removes channels from the bus. The bus is still there, it just has zero channels. Is it normal for a host to remove bus channels?

Here is an example, where my debugging variable channelCountBus1 shows getNumChannels() for bus 1 (“Voice 2”):

Initial I/O matrix in Reaper


Screen Shot 2020-06-22 at 9.19.48 am

After adding pins for bus 1


Screen Shot 2020-06-22 at 9.19.48 am

After removing pins from bus 1


Screen Shot 2020-06-22 at 9.19.25 am

It tripped me up because my processBlock was defining write pointers to non-existent channels. I can guard against this by testing that the channels exist, but my preference would be that the host didn’t delete them in the first place.

My bus setup looks like this. I have 7 buses for my drum voices, and 9 empty buses to bring the total to 16 (having read that Logic requires 16 buses):

: AudioProcessor (BusesProperties()
                .withOutput ("Voice 1", AudioChannelSet::stereo(), true)
                .withOutput ("Voice 2", AudioChannelSet::stereo(), true)
                .withOutput ("Voice 3", AudioChannelSet::stereo(), true)
                .withOutput ("Voice 4", AudioChannelSet::stereo(), true)
                .withOutput ("Voice 5", AudioChannelSet::stereo(), true)
                .withOutput ("Voice 6", AudioChannelSet::stereo(), true)
                .withOutput ("Voice 7", AudioChannelSet::stereo(), true)
                .withOutput ("Empty 1", AudioChannelSet::stereo(), false)
                .withOutput ("Empty 2", AudioChannelSet::stereo(), false)
                .withOutput ("Empty 3", AudioChannelSet::stereo(), false)
                .withOutput ("Empty 4", AudioChannelSet::stereo(), false)
                .withOutput ("Empty 5", AudioChannelSet::stereo(), false)
                .withOutput ("Empty 6", AudioChannelSet::stereo(), false)
                .withOutput ("Empty 7", AudioChannelSet::stereo(), false)
                .withOutput ("Empty 8", AudioChannelSet::stereo(), false)
                .withOutput ("Empty 9", AudioChannelSet::stereo(), false)),

And this is where I get into trouble after the I/O pins are removed in Reaper:

AudioSampleBuffer audioBusBuffer1 = getBusBuffer(buffer, false, 1);
float* outL1 = audioBusBuffer1.getWritePointer(0); // nope! channel no longer exists
float* outR1 = audioBusBuffer1.getWritePointer(1); // nope! channel no longer exists

TLDR: Is it normal for a host to be able to remove channels from a bus? What is an appropriate way to guard against this possibility?

After some further research I’m beginning to realise that the host can do whatever it likes with the output buses.

@fabian’s contributions to this thread were very instructive.

So I guess the correct approach is to check that an output bus exists and has channels before trying to send audio to it. Which sounds pretty obvious when I write it like that!