nightscout / nightscout/AndroidAPS
DynISF 24h average ISF for Bolus Wizard/COB is lost after app restart
Nobody has claimed this yet.
- Dominant language
- Kotlin
- Stars
- 1.2k
- Forks
- 6.4k
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 19
Description
DynISF 24h average ISF for Bolus Wizard/COB is lost after app restart
Summary
When Dynamic ISF (DynISF) is enabled, the value shown as “ISF for Calculator and Carbs Absorption” does not reliably preserve the expected 24h average across app restart.
In my case, after restarting AAPS, the startup path reports:
Loaded 0 variable sensitivity values from database
and then getAverageIsfMgdl() returns:
null from 0 values
until new live DynISF calculations occur. After the first live calculation, the “24h average” becomes equal to that fresh sample (or a very small number of fresh samples), rather than the persisted 24h history.
This appears to affect the value used for Bolus Wizard / calculator and COB / carbs absorption, not only the display.
Affected version
- AAPS 3.4.0.0 (db72)
Relevant setup
- Dynamic ISF enabled
- Static profile ISF: 1.9 mmol/L/U
- DynISF adjustment factor had been changed to 120% earlier that day
- Issue persists after manually restarting AAPS multiple times
Problem description
Before restart, AAPS had a non-empty DynISF average for calculator/COB.
After restart, AAPS failed to reload historical variable sensitivity values into the cache used by getAverageIsfMgdl(), and the average collapsed to null / 0 values, then to only the newly generated post-restart sample(s).
This makes the shown/used “24h average” dependent on successful cache warm-up rather than persisted APS history.
Expected behavior
After app restart, AAPS should reconstruct the DynISF 24h average for Bolus Wizard / COB from persisted APS history.
The value shown as “ISF for Calculator and Carbs Absorption” should remain stable across app restart and should not reset to:
null from 0 values, or- a single fresh post-restart DynISF sample such as
19.7 from 1 values
unless there is genuinely no relevant historical data.
Actual behavior
After restart:
- AAPS logs:
Loaded 0 variable sensitivity values from database
getAverageIsfMgdl()returns:null from 0 values
- Once the first new live DynISF value is calculated, the “24h average” becomes that single value:
19.7 from 1 values
- The value shown in the UI for “ISF for Calculator and Carbs Absorption” then reflects that tiny post-restart sample set rather than the persisted 24h average.
Evidence from logs
After restart, historical DynISF cache warm-up fails
19:05:24 OpenAPSSMBPlugin.onStart(): Loaded 0 variable sensitivity values from database
19:14:58 OpenAPSSMBPlugin.onStart(): Loaded 0 variable sensitivity values from database
The average then becomes empty
getAverageIsfMgdl() null from 0 values
This occurs repeatedly after restart.
A fresh live DynISF sample is then calculated
calculateRawDynIsf(): variableSensitivity=19.7
The “24h average” then becomes just that one fresh sample
getAverageIsfMgdl() 19.7 from 1 values
Later it grows only as more fresh post-restart values accumulate, for example:
getAverageIsfMgdl() 19.05 from 2 values
getAverageIsfMgdl() 19.366666666666667 from 3 values
Persisted APS results do appear to contain the relevant data
Example inserted APSResult includes both:
glucoseStatusJson={... "glucose":146.0 ...}variable_sens=19.7
So historical DynISF-related data appears to be persisted, but the startup reload path still ends up with 0 usable values.
Why this looks like a real bug
This does not appear to be just a UI mismatch.
The log indicates that:
- the average used by
getAverageIsfMgdl()is backed by an in-memory cache, - that cache is supposed to be rehydrated on startup from persisted APS results,
- startup rehydration can fail and leave the cache empty,
- after that, the “24h average” becomes dependent only on fresh post-restart samples.
This means restart can materially change the value used by the calculator / COB logic even when persisted historical APS data exists.
Suspected root cause
Based on observed behavior, the problem appears to be in the startup/cache-rehydration path around OpenAPSSMBPlugin:
onStart()tries to rebuild the DynISF cache from persisted APS results- only rows with all required fields are accepted
- if that warm-up path yields zero usable rows,
getAverageIsfMgdl()has no historical basis - the next live DynISF calculation then seeds the cache with only 1 value, producing misleading output such as:
19.7 from 1 values
So there are likely two related design/implementation issues:
- Startup rehydration can fail even though APS results with DynISF/glucose data exist
getAverageIsfMgdl()depends on transient in-memory cache rather than directly computing from persisted APS history
Even if the startup bug is fixed, the second point still makes the behavior fragile.
Suggested fix
A more robust implementation would be:
- Compute the Bolus Wizard / COB DynISF 24h average directly from persisted APS history rather than relying on a transient cache alone
- Improve startup logging to show:
- number of APS results queried
- number skipped due to missing
glucoseStatus - number skipped due to missing
variableSens - number actually loaded into the cache
- Optionally, if a historical DB hit is used for DynISF, backfill the cache immediately so the average does not remain artificially tiny after restart
Impact
This can make the value shown and used for:
- Bolus Wizard / calculator
- COB / carbs absorption
depend on whether the app has recently restarted, which is undesirable and potentially clinically relevant.
Reproduction notes
This was observed in real use, but it should be reproducible with a setup that has:
- DynISF enabled
- sufficient APS history over the last 24h
- app restart
- inspection of logs around
OpenAPSSMBPlugin.onStart()andgetAverageIsfMgdl()
Attachments
I can provide:
- full log zip
- screenshots showing the UI value for “ISF for Calculator and Carbs Absorption”
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with OpenAPSSMBPlugin.onStart() and trace how persisted APS results are loaded into the cache used by getAverageIsfMgdl(). Reproduce an app restart with recent DynISF history, compare the queried rows with the logged loaded count, and inspect calculateRawDynIsf() for cache updates. Done means the 24-hour calculator/COB average is restored from relevant persisted history after restart and remains backed by more than only new samples.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- kotlin
- Domain
- databases, mobile-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100