Error dialog when downloading form with last-saved

Thank you for implementing this feature it is going to be really useful for our enumerators (and save me some ear ache). I have a couple of issues.

Firstly, when downloading a form with last-saved for the first time I keep getting an error:
Unable to parse external secondary instance:java.ioFileNotFoundException: /storage/emulated/0/odk/forms/1581429444770/last-saved.xml(No such file or directory)
Problem found at nodeset: html/head/model/instance With element
Copying media files failed.

The only way I’ve managed to get around this is using another form to save an image – therefore creating a folder on the device. Am I doing something wrong?

Once I have downloaded the form I’m also getting issues relating to used last-saved in for question within repeats. When I save a form with more than one repeat I get the error:

XPath evaluation: type mismatch
This field is repeated:
instance(__last-saved)/data/welfare_repeat[1]/Q2x1[1]: instance(__last-saved)/data/welfare_repeat[2]/Q2x1[1]: instance(__last-saved)/data/welfare_repeat[3]/Q2x1[1]

You may need to use the indexed_repeat() function to specify which value you want.

Attached is an example.
SCOPING_Last_saved.xlsx (32.7 KB)

Thanks for the quick report, @Stuart. I'm glad the feature will be helpful to you.

Indeed. I have filed the issue at https://github.com/opendatakit/collect/issues/3635 and hope to have it fixed shortly. This is due to an unexpected interference with the map view feature. In fact, the error doesn't matter and is safe to ignore. Everything should work correctly once you fill the form. Is this what you see? I didn't notice this when doing the XLSForm update because I pushed my test form directly to Collect instead of downloading it to a server.

I intended to clarify in the documentation that last-saved is not supported for repeats but I forgot to do this! Thanks for the reminder.

The reason it's not supported is because multiple filled records likely don't have the same number of repetitions so it's unclear what correspondence to make between different records. In this case, what do you expect it to do? It looks like perhaps what you'd like to do is to use the value from the last saved instance of the repeat?

Thanks for getting back to me so quickly. The first error I mentioned is when i'm getting the blank form so I can't actually download the form to fill in to being. I had a thought last night that it appears to be due a directory not being created for the form, i'm going to try and add images to the example that I posted to see if this forces it to create a directory.

The last-saved not working within repeats is an issue as most of our question (shortened version attached as an example) are within a repeat group i.e location info is collected then multiple animals are assessed at that location. Looking at the error that i've been getting could it not just default to the last saved repeat i.e the defualt would be instance(__last-saved)/data/welfare_repeat[3]/Q2x1[1]?

If the form doesn't include other media files, you can go to Fill Blank Form and it should be discovered and properly processed at that time.

Unfortunately that won't work. I have a fix up at https://github.com/opendatakit/collect/pull/3639 that I'm hoping will get reviewed in the next couple of days and then we'll publish Collect v1.25.2 to fix this.

The last-saved feature allows you to query the last filled record. It looks like what you want to do is to use a value from the last repeat instance as a default for the current repeat instance, is that right? This is also a very useful thing to do and doesn't require the last-saved feature. Here is a sample form that does this.

The expression in the default column is:
if(position(..) >= 1, /data/child_details[position() = position(current()/..) - 1]/child_school, '')

The position() = position(current()/..) - 1 part is what accesses the last instance of the repeat. It's in square brackets to filter the list of all repeat instances (it's an XPath predicate).

The if(position(..) >= 1, ..., ...) part is important because you don't want to try to access a repeat with index -1.

child_details should be replaced by the name of your repeat.

child_school should be replaced by the name of the question in the repeat that you are trying to use as a default.

I don't believe this can be simplified but I'm interested in hearing whether anyone else might have an alternative way of expressing this.

Thank for all your work on this. You're absoultly right i need to use a value from the last repeat instance as a default for the current repeat instance i've added the if statement and it works like a charm :slight_smile: I'll have some very happy enumerators.

1 Like

Thanks again for quickly pointing out the crash. Collect v1.25.2 is now out and should fix it.