Unexpected Type/Invalid Value errors when using WatchUi.getCurrentView()

I am still working through a few issues I am seeing in the ERA viewer for my app, and I have come across another one where I would appreciate some input from the community.

In my app, I have a class ErrorView, which is a full-screen view used to display error messages. The class contains helper functions that use WatchUi.getCurrentView() to determine whether an error view is currently being shown.

In all my local tests, this works reliably under various conditions, including calls made during getInitialView(), where no view has been pushed yet.

However, there are reports of an Invalid Value error and an Unexpected Type Error occurring on a Fenix 8 Pro and an Edge 1040. These errors occur during startup and at another, later point.

Below is the relevant code with line numbers:

38 // Returns the error view if is shown, or otherwise null
39 private static function get() as ErrorView? {
40     var view = WatchUi.getCurrentView()[0];
41     if( view instanceof ErrorView ) {
42         return view;
43     } else {
44         return null;
45     }
46 }
47
48 // Determins whether an error view is currently showing
49 public static function isShowing() as Boolean {
50     return WatchUi.getCurrentView()[0] instanceof ErrorView;
51 }

And here are the corresponding errors with stack traces from the ERA viewer:

Error Name: Invalid Value
Devices:
    fēnix® 8 Pro 47mm / 51mm / MicroLED / quatix® 8 Pro 47mm / 51mm: 21.12
Backtrace:
    ErrorView.<globals/ErrorView/<statics>/<>get>:40
    ErrorView.createOrUpdate:26
    OHApp.getInitialView:76

Error Name: Unexpected Type Error
Devices:
    fēnix® 8 Pro 47mm / 51mm / MicroLED / quatix® 8 Pro 47mm / 51mm: 21.12
Backtrace:
    ErrorView.<globals/ErrorView/<statics>/<>get>:41
    ErrorView.createOrUpdate:26
    OHApp.getInitialView:76

Error Name: Unexpected Type Error
Devices:
    Edge® 1040 / 1040 Solar: 30.12
Backtrace:
    ErrorView.isShowing:50
    SitemapRequestTasks.invoke:188
    AsyncTaskQueue.executeTasks:119

In all three cases, the errors occur either when accessing WatchUi.getCurrentView() or when checking the type of its result using instanceof. Since these helper functions do not do much beyond that, the line references reported by ERA seem accurate.

What I do not understand is under which circumstances WatchUi.getCurrentView() or an instanceof check could result in these errors.

Any hints or ideas would be very welcome.

For reference, here is the full source file:
https://github.com/openhab/openhab-garmin/blob/main/source/user-interface/error-handling/ErrorView.mc

Regards, Robert

Top Replies

All Replies

  • It should be straightforward to ensure that your code consistently uses this custom implementation for pushing and popping views. I have actually been using it for quite some time to track the number of views on the stack, allowing me to pop all views except the base view and reliably return to it.

    I am not aware of any cases where the API itself pushes or pops views in a way that would bypass this handler. In my application, this does not occur. However, there may be parts of the API with which this approach is not compatible.

    I will roll this out to my beta channel now, and ask users to test it. I am already in contact with one user who encounters this issue quite frequently.

  • I haven't tried it, just read the code, but I think you have a bug.

    In popToBottomAndSwitch you leave the 1st (bottom) view and don't replace it with the view, delegate passed (what Garmin does, when you call WatchUI.switchToView in the last line as far as I understand) so you definitely get out of sync when you pass a different view and delegate than what was the initial view.

    Or maybe I don't understand (from the docs) what switchToView does when you call it and you only have the bottom view?

    I think you should instead add switchToView in this class, and move the strangely named popToBottomAndSwitch to somewhere else (and maybe rename it :) I think popAll() would make more sense, and then you could call switchToView(v, d)

  • I’m not convinced that the custom view stack getting out of sync explains what we’re seeing here. In my case (and it sounds similar to Robert’s), the crash consistently occurs on the type comparison itself. Either:

    _pageMenu.equals(WatchUi.getCurrentView()[0])

    or 

    if (currentView instanceof SomeClass)

    The exception is thrown directly on that comparison line, not somewhere deeper in the call chain. ERA reports either Invalid Value or Unexpected Type, and it’s always at the point where the returned array element is accessed or type-checked.(Occasionally ERA points to a nearby line, but that’s a known quirk.)

    The software version correlation doesn't point to app side issues:

    - I have zero crashes on 29.xx software.
    - The issue appeared with 30.xx beta firmware.
    - After I first reported it (Jan 7), Garmin acknowledged it about a month later.
    - A beta released the same day as the acknowledgement (30.17) drastically reduced the crash frequency.
    - I can no longer reliably reproduce it, but ERA still shows occasional reports on 30.17+.

    That behavior strongly suggests a firmware/runtime issue rather than an app-level logic error.

    If a simple type comparison (instanceof or equals) can throw Invalid Value or Unexpected Type, something deeper seems unstable especially when the behavior changes between firmware revisions without any app changes.

    I’m definitely open to workarounds (like maintaining a custom view stack), because I don't know when we'll see this resolved and I'd rather it doesn't affect my user base. That being said, based on the version correlation alone, it’s hard to see how this isn’t at least partially SDK/runtime related.

  • I haven't tried it, just read the code, but I think you have a bug.

    Thanks for catching that. You’re absolutely right, I missed switchToView. I’ve just committed an updated version that handles this case as well.

    Regarding the strange name, I have now renamed it to resetTo.

  • I’m not convinced that the custom view stack getting out of sync explains what we’re seeing here.

    Yes, the custom view stack is unrelated to the underlying issue. @flocsy simply pointed out a problem in my workaround.

    I’m definitely open to workarounds (like maintaining a custom view stack), because I don't know when we'll see this resolved and I'd rather it doesn't affect my user base.

    I’ll let you know if it works. There is, of course, a chance that WatchUi.getCurrentView() is not the actual problem, but rather the View class itself. In that case, a custom view stack would not help.

  • I’m not convinced that the custom view stack getting out of sync explains what we’re seeing here.

    Yes, the custom view stack is unrelated to the underlying issue. @flocsy simply pointed out a problem in my workaround.

    Oh my bad I didn’t read through your workaround properly. That’s on me.

    Yeah, I still feel like something’s off with WatchUi.getCurrentView() (or what it’s returning). A basic instanceof / equals throwing those errors just doesn’t feel right. Whether it’s that call specifically or something deeper in View, hard to say. It definitely seems like an SDK issue more so than app logic, everything we're doing seems tickety boo according to the SDK docs.