Crash on real device (Array Out Of Bounds) when updating CustomMenu - sideloading & settings?

Hi all,

I'm currently facing a crash that only occurs on my physical device (Epix 2 Pro). The same test case runs fine in the simulator.

The issue happens when the app manipulates a CustomMenu - specifically when removing items or replacing them using CustomMenu.updateItem(). On the device, this causes a crash.

I was able to retrieve the CIQ_LOG, which reports an "Array Out Of Bounds Error", but it doesn't include a stack trace. Here's the relevant part of the log:

Error: Array Out Of Bounds Error
Time: 2025-05-19T19:36:09Z
Part-Number: 006-B4313-00
Firmware-Version: 20.22
Language-Code: eng
ConnectIQ-Version: 5.1.1
Store-Id: 8a6b62f1-5450-4912-8799-2eeaf9779d97
Store-Version: 44
Filename: F56A2548
Appname: openHAB
Stack:

Now to my main questions:

  1. To get a proper stack trace, I assume I need to sideload a debug build - is that correct?

  2. If I sideload the debug build, is there any way to preserve the user settings from the store-installed version? Or do I have to hardcode them in the debug build?

  3. Has anyone run into similar CustomMenu update crashes on-device but not in the simulator?

Thanks in advance for any help or suggestions!

  • Does anyone know how can I generate debug logs (e.g., System.println) from my app on the device?
    I found some old log files in the GARMIN\Apps\LOGS folder on my watch that contained System.println output. However, I haven’t been able to generate any new logs.

  • You have to create the ,txt file for your app with the correct name.  If you'd installed from the store and then copy a sideload, it will use the 8 character store name (F56A2548 in the log file you posted)  Uninstall your store version before you copy the sideload if you don't want the name to change.

  • The debug build didn’t help. I hard-coded all the settings and side-loaded the app, but the error messages in the CIQ log still don’t include a stack trace. Is there something else I could do to get that stack trace?

  • Create your own <appname>,txt file with the proper app name and you'll see your System.println calls.

  • Thanks, that helped! By creating a file named after the local app ID (e.g., F56A2548.txt), I was also able to capture logs from an app installed via CIQ.

    It seems the issue is related to CustomMenu.deleteItem. The exception isn’t thrown directly by that method but appears to occur later, outside of my own code. It looks like the item is deleted successfully, but then—possibly during a menu redraw—something on Garmin’s side fails, perhaps because there’s now one fewer item than expected.

    Has anyone successfully used CustomMenu.deleteItem in a real device (not just the simulator)? In the simulator, it works exactly as expected: the item is gone on the next redraw.

  • It looks like the issue is limited to the currently displayed CustomMenu. If I delete a menu item from a CustomMenu that’s not currently visible and then push it onto the view stack later, it works without any problems.

  • Yeah, that makes sense. It's always tricky to change collections while they are being used.

    Can't you pop the view and push it again after you deleted the item, so it is being redrawn?

  • Yes, I’m currently working on a workaround. It would be much easier if the simulator behaved the same as the real device. In my case, the root view is also a CustomMenu, and there's a hierarchy of nested menus. Updates can potentially affect all CustomMenu instances.

    I now need to test whether calling switchToView with the same view is enough to resolve the issue, or if I need to temporarily switch to a different view in between to force the CustomMenu to reset whatever internal state is causing the problem.

  • By the way, the issue also affects the opposite case: adding a menu item. On the real device, the new item only appears after leaving the current CustomMenu and re-entering it. In contrast, the simulator updates the menu immediately.

  • If I sideload the debug build, is there any way to preserve the user settings from the store-installed version? Or do I have to hardcode them in the debug build?

    1) Determine the filename of your store-installed app's PRG by copying GarminDevice.xml off your watch and opening it in a text editor (you will want to beautify it)

    2) The name of settings file will be the same as app PRG name, except the extension is SET. e.g. STOREAPPNAME.PRG => STOREAPPNAME..SET

    3) Copy \GARMIN\APPS\SETTINGS\STOREAPPNAME.SET so the filename (sans extension) matches the name of the sideload. e.g. STOREAPPNAME.PRG => SIDELOADNAME.SET