Exception loading properties. Unable to see exact reason

Hi,

Over the last week my app has crashed on over 70 devices which means there's a new bug. It crashes at

if(!  isSessionRecording()
           || AppConfig.isAutoLapEnabled()==null
           || !AppConfig.isAutoLapEnabled()
           || AppConfig.getLapDistance() ==null
           || AppConfig.getLapDistance() < 0.01){
            return null;
        }
        
....

 public function getLapDistance(){
        return Properties.getValue("auto_lap_distance");
    }

public function isAutoLapEnabled(){
        return Properties.getValue("auto_lap_enabled");
    }
    
public function isSessionRecording(){
        return mSession!=null && mSession.isRecording();
    }
...

properties.xml
...
<property id="auto_lap_distance" type="float">1</property>
...

 <setting propertyKey="@Properties.auto_lap_distance" 
                 title="@Strings.auto_lap_distance_title"
                 prompt="@Strings.auto_lap_distance_prompt">
            <settingConfig type="numeric" min="0.1" max="99"/>
</setting>

I recently changed property type of lap distance from number to float in the properties because I wanted it to be 0.01 -> 99 (km/miles) rather than 1-99,000 (m).

The exception is:

Error Name: Unhandled Exception
Occurrences: 74
First Occurrence: 2021-09-08
Last Occurrence: 2021-09-14
Devices:
fēnix® 6 / 6 Solar / 6 Dual Power: 16.70
fēnix® 5 Plus: 15.40
Upcoming Wearable: 4.67
fēnix® 6X Pro / 6X Sapphire / 6X Pro Solar / tactix® Delta Sapphire / Delta Solar / Delta Solar - Ballistics Edition / quatix® 6X / 6X Solar / 6X Dual Power: 19.20
fēnix® 6X Pro / 6X Sapphire / 6X Pro Solar / tactix® Delta Sapphire / Delta Solar / Delta Solar - Ballistics Edition / quatix® 6X / 6X Solar / 6X Dual Power: 16.80
Descentâ„¢ Mk2 / Descentâ„¢ Mk2i: 4.20
Forerunner® 245: 7.80
vívoactive® 4: 6.30
vívoactive® 3: 7.80
vívoactive® 4S: 6.30
App Versions: 0.0.30
Languages: ces, cht, dut, eng, fre, gre, hun, ind, lit, pol, rus, slo, spa
Backtrace:
SessionManager.checkAutoLap:285
BaseView.handleTimer:135
MapperView.handleTimer:194

Line 285 is the If condition. I wondered if there's now some data of the wrong type in lots of device memory, or something else is subtly wrong.  Is there any way to determine what the issue is that I haven't thought of? I cannot recreate it locally and the exception is pretty vague.

If have temporarily added:

try{
            lastLapStats= mSessionManager.checkAutoLap();
        }catch(ex){
            //System.println("Exception processing autolap:" + ex);
        }

and the below to the 'if' condition in the hope that hides the problem

|| !( AppConfig.getLapDistance() instanceof Toybox.Lang.Float)

but I'm not confident auto-lap will be working on all devices unless they update the lap distance value themselves (causing it to re-save), or do something else to ensure the value is compatible.

Should I, for example, change the property name and accept that everyone will have their auto-lap distance reset (or perhaps I'm missing the real bug in the code above)?

  • When you try to reference something with Properties and the key doesn't exist, it will throw an exception.

    Put the Applicantion.Properties.getValue inside a try/catch.  

  • Should it default to 1, or am I misunderstanding how it works? I couldn't see how it would possible for it to be undefined.

    I can try in the try/catch to be defensive.

    Thanks 

  • This is a CYA in case something odd happens and it sounds like it's happening for you..  In the catch, supply a default.

  • Sounds like people have already been setting auto_lap_distance as a number from 1-99,000, and now it's a float from 0.01 to 99.

    In the past, I found behavior in Garmin Connect where setting an invalid value for an app setting (e.g. a non-number for a number) causes the corresponding property to be set to null. This could be something similar. i.e. Perhaps if they set their auto lap distance to 10,000 before the update, then if they go back to their settings after the update, the field is cleared out (set to null) because 10,000 is out of range.

    If you wanted to migrate the old setting cleanly you could've done the following:

    1) Remove auto_lap_distance from app settings

    2) Add auto_lap_distance2 to app settings

    3) When app starts up, check for existence of auto_lap_distance. If present, you could divide it by 10,000 and save the result to auto_lap_distance2. Then you would have to set auto_lap_distance to null (if possible) or delete it (only problem here is that newer CIQ 4.0 devices don't support deleting properties, so hopefully it would be possible to just set it to null)

    However, there would still be the the loophole where the user could go to app settings immediately after updating, in which case the old field wouldn't be migrated.

    In the case of float and number settings, I think you definitely want to check for null, since there's been known issues past, even in the absence of a situation like yours.