Control Surface: why does this simple code brick my ATmega32U4 boards?

I have had some issues with a ATmega32U4 board (Arduino Pro Micro) essentially getting ‘bricked’ after programming it, I think it always happened when using the control surface library. By bricking I mean it doesn’t do what it is programmed to do and it completely stops from showing up when connected over USB. The only way to save it is to use another external board to rewrite the bootloader. (This is annoying as the board is soldered into a circuit).

I assumed that my board was faulty and got a bunch of new ATmega32U4 boards (Pro Micro and Leonardo). But the exact same thing happens to all of them. I’ve found a simple example where this happens:
(WARNING: THIS CODE MIGHT CORRUPT YOUR BOOTLOADER)

#include <Control_Surface.h>

USBMIDI_Interface midi;
 
using namespace MIDI_Notes;

AnalogMultiplex<3> mux = {
  A3,
  {2, 3, 4},
  6,
};
AnalogMultiplex<3> mux2 = {
  A3,
  {2, 3, 4},
  7,
};

NoteButton button[] = {
  {mux.pin(7), MCU::MUTE_1},
  {mux.pin(6), MCU::SOLO_1},
  {mux.pin(5), MCU::MUTE_2},
  {mux.pin(4), MCU::SOLO_2},
  {mux.pin(3), MCU::MUTE_3},
  {mux.pin(2), MCU::SOLO_3},
  {mux.pin(1), MCU::MUTE_4},
  {mux.pin(0), MCU::SOLO_4},
  {mux2.pin(1), MCU::PLAY},
  {mux2.pin(4), MCU::STOP},
  {mux2.pin(5), MCU::REWIND},
  {mux2.pin(8), MCU::FAST_FWD},
  {mux2.pin(7), MCU::RECORD},  
};

void setup() {
  Control_Surface.begin();
}
 
void loop() {
  Control_Surface.loop()
}

However, the following code does not have this problem:

#include <Control_Surface.h>

USBMIDI_Interface midi;
 
using namespace MIDI_Notes;

AnalogMultiplex<3> mux = {
  A3,
  {2, 3, 4},
  6,
};
AnalogMultiplex<3> mux2 = {
  A3,
  {2, 3, 4},
  7,
};

NoteButton button[] = {
  {mux.pin(7), {note(C, 4)-7, CHANNEL_1}}, 
  {mux.pin(6), {note(C, 4)-6, CHANNEL_1}}, 
  {mux.pin(5), {note(C, 4)-5, CHANNEL_1}}, 
  {mux.pin(4), {note(C, 4)-4, CHANNEL_1}}, 
  {mux.pin(3), {note(C, 4)-3, CHANNEL_1}}, 
  {mux.pin(2), {note(C, 4)-2, CHANNEL_1}}, 
  {mux.pin(1), {note(C, 4)-1, CHANNEL_1}}, 
  {mux.pin(0), {note(C, 4), CHANNEL_1}},
  {mux2.pin(7), {note(C, 5), CHANNEL_1}}, 
  {mux2.pin(6), {note(C, 5), CHANNEL_1}}, 
  {mux2.pin(5), {note(C, 5), CHANNEL_1}}, 
  {mux2.pin(4), {note(C, 5), CHANNEL_1}}, 
  {mux2.pin(3), {note(C, 5), CHANNEL_1}}, 
  {mux2.pin(2), {note(C, 5), CHANNEL_1}}, 
  {mux2.pin(1), {note(C, 5), CHANNEL_1}}, 
  {mux2.pin(0), {note(C, 5), CHANNEL_1}}, 
};

void setup() {
  Control_Surface.begin();
}
 
void loop() {
  Control_Surface.loop()
}

Does anybody know why this happens?

 {mux2.pin(8), MCU::FAST_FWD},

Your multiplexer only has 8 pins, index 8 is out of bounds for an array of length 8. The valid indices are 0-7.

I highly doubt that the code corrupts your bootloader, it's much more likely that it just crashed your program, causing the USB connection to stop working as well (which runs on the same processor after all).
Simply resetting the board right before uploading should fix it, there's no need to flash a new bootloader.

Pieter

Oh wow, I can't believe I made such a stupid and trivial error. I need to look into my longer code to see whether it was the same issue.

The reason I think the bootloader somehow gets corrupted is that I couldn't make it work by resetting it. I then tried to load another program, say a simple blink program, using an external board. This made the original board appear when connected through USB, however it automatically disconnected whenever you tried to program it. Only way I could make it behave normally again was to flash a new bootloader.

I've just tried your code on an Arduino Leonardo, and as expected, the USB connection disappears after uploading.
To "fix" the Arduino, press the reset button, then select the serial port that shows up (Tools > Port). You have to select the port while the LED is fading, before the bootloader ends. Compile (verify) some working code (e.g. Blink) so it's ready to upload. Then click upload and immediately press the reset button on the Arduino.

PieterP:
I've just tried your code on an Arduino Leonardo, and as expected, the USB connection disappears after uploading.
To "fix" the Arduino, press the reset button, then select the serial port that shows up (Tools > Port). You have to select the port while the LED is fading, before the bootloader ends. Compile (verify) some working code (e.g. Blink) so it's ready to upload. Then click upload and immediately press the reset button on the Arduino.

Thanks a lot for this. I will try it out. I really appreciate all your help.