safeMutableData.getVersion() FAILED due to invalid container handle

@bochaco I have now posted this on github: issue #91

I have a live app on Alpha2 which is behaving oddly, quite likely my fault, but possibly a bug in the API.

The issue is that while I am using safeMutableData.getVersion() successfully most of the time, I can also reliably cause it to fail with an ‘invalid handle’ error, although the handle it reports as invalid is as expected, so I don’t know why it thinks it is invalid.

To reproduce:

  1. Login to an account on Alpha2 and visit safe://litewrite.rsports - this is a simple note taking app which allows you to create notes offline or online, and syncs them to SAFE storage when online.
  2. Create a note (the app is offline at this stage), by clicking the ‘+’ top left, and entering text in the area just to the right. The first line of the text serves as a document title, and a menu entry will be added to the left, under the ‘+’.
  3. Connect to SAFE by clicking the SAFE icon in the top right of the litewrite display. Notice the activity in the debug console: you’ll see the appHandle and a delay while you authorise litewrite, after which the handle for the MD container, and an ‘emulate as NFS’ handle are printed for later reference by a function called _getMdHandle (search for the latter in the console output if you can’t find the messages).
  4. In the console you will see lots of activity following connection, and at this point I believe there will not be any errors (but I can’t be sure of that as I have made some code changes since I had a clean account to play with). You will also notice that so long as you remain connected, the console shows a flurry of output every ten seconds, when the RS.js core of the app attempts to sync local storage (IndexDB entries) with files it creates in the root container, in /remotestorage/documents/notes/. This includes stuff to show me that my code is accessing the container and generating a directory listing by filtering the results of window.safeMutableData.getEntries(self.mdRoot) - which is successfully using the handle which the error reports as invalid. See _getFolder implementation for that call to window.safeMutableData.getEntries(self.mdRoot). Notice that _getFolder is successfully calling the function that is later generating an error (window.safeMutableData.getVersion(self.mdRoot)) and with the same MD handle.
  5. Set a breakpoint (if you like) at the line in litewrite.min.js containing the text ‘safeMutableData.getVersion() FAILED’
  6. Create a new note (click the ‘+’) and type a few characters. This will force an immediate attempt to sync with the network and is when I get the error. Repeat this until you get the error in the console (or hit that breakpoint). For me I get it every time now.

I may be doing something wrong in how I’m using the API, or maybe I’m triggering a bug in it, or? I’m not really sure how to debug this without getting into the browser code and I’m not ready to do that! Any ideas, help appreciated. Thanks.

If anyone else want to try the above and report whether they get this error (or others) or not, please do, it may be helpful.

I apologise now for the structure of the code to any who open it - I’m still a newb on how best to use promises, handle errors etc. Tips gratefully received from everyone :slight_smile:

2 Likes

Hi @happybeing, I spent some time debugging your app, and what I’m seeing is that when you perform step 6 from your instructions, a page refresh event is triggered somehow in the browser which causes that the handles are all being freed for the page, I didn’t dig deeper than that. Can you please try to figure out what could be triggering our page refresh event as part of step 6 when clicking the '+' to add a note?
Do you intentionally try to refresh the page at that point or could it be done by some framework/iib you are using?

Edit: I can also see the same effect when clicking on any of the already created notes

2 Likes

Eek, thanks very much for the super fast response, as usual! Unfortunately it’s not my app, and I guess it does this by design.

My part is in creating a fork of remoteStorage.js which uses the SAFE API for storage rather than a remoteStorage server. There are several decent open source apps built using remoteStorage.js, so I’m working on this to port them quickly to SAFEnetwork. (One is an Evernote clone for example).

So I guess one solution would be to have an API option of preserving handles through a page refresh.

Another would be for me to detect the event, but I think it would possibly add quite a delay to the application renewing the handles each time. It might also require the user to re-authorise manually? If so, not a good solution.

I’m not sure how common this situation will be, apps wanting to refresh a page while maintaining state, but I expect we’ll encounter it again so it might be worth considering the value of making this an option. What do you think?

I’ve gone thru all those thoughts as well, and still thinking about it. What I’d like to understand now is if that website is effectively being refreshed or our event is being triggered incorrectly, that’s why if you eventually dig deeper and confirm it, please let me know.

1 Like

I’ll have a look but I’m not sure I can figure out the app code - if not I will try asking the authors.

1 Like

Update…

I’m fairly sure that the application changes part of the URL each time you select / create a document, but that this doesn’t reload the page because it is only changing the URL hash (which doubles as the app’s document id):

safe://litewrite.rsports/#!(FFBC74EF-B845-4395-B2D5-87DDD9B78119)-heres-an-offline-note---26-sept-17-15:15

So I’m not sure if this should cause SAFE Browser page refresh or not. If not, your bug wOOt!? If it should, ‘my’ problem, or rather an application specific problem and still wondering how to work around :frowning_face: Fingers crossed for the former :slight_smile:

@bochaco In addition to the above update, I have now tried a second app from a different author and this one hits the same problem - one thing in common is that it occurs at the point where this app also changes the URL hash. When you choose a menu item, the URL hash is updated (part of the page changes but I don’t think the page is reloaded). I think this may be a fairly common feature of single page apps.

There’s a live version on the web: https://lduboeuf.github.io/team-tool-box

Here it is on SAFE: safe://tt2

In either you can do something like:

> My Groups > Add a group
	'member1' > Add # oops, should have typed 'group1'
		'm-a' > add
		'm-b' > add
		'm-c' > add
		'm-d' > add
		
	> Home > Find Members 
		'2' > ok
		> Save Result
			'first save' / 'description of first save'

If you do this before connect/Allow, all is fine. After connect (click SAFE icon top right) and Allow, you’ll see activity in the console and this is fine until you choose one of the menu items and the URL hash changes. After that the handles become invalid and the SAFE DOM errors appear.

Hope this helps!

@bochaco FYI: one of the remoteStorage devs raised a question as I was asking for info related to this problem. He was concerned that the SAFE Browser might not be supporting the history api correctly. You can see his concerns here from [15:54].

Thanks @happybeing, I’ll be taking a look at all this.

EDIT: just FYI, this was added to our TODO list: https://maidsafe.atlassian.net/browse/MAID-2390

1 Like

Just to clarify here, pushState seems to work fine in the browser in general, (running history.pushState({}, 'yes', '#gogo') in the console changes the page title/url without a refresh, eg. So I don’t think it’s that.

I don’t think we should enable this with a refresh. Certainly pushState should not free handles as it does now, but a refresh should start the app fresh. I also think leaving handles open could be abused somehow, as well as it raising questions of how long to keep handles etc.


I think, in the app (going off of heresay, i havent tested yet), if the refresh happens on clicking a link, that’s normal (it’s opening a new page that is the same page with a new anchor). The app should be preventing normal navigation onClick via e.preventDefault(), and then handling the hash change itself. (I think).

2 Likes

This appears fixed by SAFE Browser 0.7.0 (which no longer frees handles on URL hash changes).

Test app: safe://litewrite4 (on alpha2) - note you must use SAFE Browser 0.7.0 or later!

5 Likes

This topic was automatically closed after 60 days. New replies are no longer allowed.