This is normal behaviour. At some point the cache is empty on the server, but the browser is still open so the Sync between the server and what is in the browser is completely lost. You have to catch this yourself.
What are the settings of ABMShared.SessionMaxInactiveIntervalSeconds? (In my apps I set it to 3 days as it are inhouse apps)
If for example this is set to 30 minutes, then whatever happens, if the device was not able to do a heartbeat (every 30/2 minutes) because the internet connection was lost or the user closed the browser, at that point the server will kill the session after 30 minutes and the scavenger will delete the cache.
If the user now reconnects (after the 30 minutes), you'll need to reload the page (or in my apps I send it back to the entry point of the WebApp).
You can do this by putting something in the session.
e.g. I use this in WebSocket_connected BEFORE ABM.UpdateFromCache(Me, ABMShared.CachedPages, ABMPageId, ws):
If session.GetAttribute2("IsAuthorized2020", "") = "" Then
ABMShared.NavigateToPage(ws, ABMPageId, "../",False) ' go back to the apps entry point.
Return
End If
In the ABMApplication, in WebSocket_connection, I set this variable (in my case the user needs to login, but if this is not the case for you, just set the variable)
session.SetAttribute("IsAuthorized2020", "true")
So if the session is killed by jServer, the variable IsAuthorized2020 is gone, so it goes to the entry point of my app.