Collect only error for relevance from repeat field

1. What is the issue? Please be detailed.
Took me forever to track this down as I was using the same field for other calculations in the group and didn't realise where the real error location was until I made an entirely separate test form and finally found the one thing that was different between them. (╯°□°)╯︵ ┻━┻

In a form, I wanted to make a group relevant only if a field in a repeat had been answered at least once (I could have used the count of repeat elements, but if the repeat was blank the repeat count is still 1, so not ideal)

I put a simple ${input0}!='' in the relevance field, assuming that the nodeset having any content would satisfy the test. It worked in Enketo and Web Forms with no issues, but as soon as there was >1 value in Collect it errored with an 'error evaluating field ... problem located in Condition expression'

Enketo / Web Forms don't seem to be 'wrongly' only looking at the first repeat value, as leaving the input blank in the first repeat and populating the second still makes the end group relevant in both. And Collect doesn't work with the same blank then value, it still sees a repeated field and errors.

After changing the relevance to a join, with only one blank Enketo & WF don't make the group relevant, two or more blanks, Enketo & WF do make the group relevant, but Collect remains non relevant with >=2.

If this is "correct" behaviour for Collect, then Enketo and Web Forms are wrong. Or vice versa? :person_shrugging:

2. What steps can we take to reproduce this issue?
Try the attached form, see it works in Enketo & Web Forms, but not in Collect, then replace ${input0}!='' with join(' ' , ${input0}) != '' to make it work in Collect.

4. Upload any forms or screenshots you can share publicly below.

repeat relevance error.xlsx (83.2 KB)

In my view, Collect’s behavior is correct, and here’s why:

${input0} is a question inside a repeatable group. When you try to use it in a relevance expression (${input0}!='') outside of that repeatable group, the calculation engine doesn’t know which instance of ${input0} you mean (for example, if there are 3 repeats). As a result, Collect throws an error, asking you to use the indexed-repeat() function to specify the instance. I also tested your form and added another note:
Screenshot from 2026-02-17 13-40-51

to see what Enketo and Web Forms actually return in this case, it turns out they always return the value from the very first repeat group. So they are more liberal in this case. While this may seem convenient, it is not technically correct.

1 Like

Thanks for the explanation. I had assumed that a check of !='' would work to check if there was any content, but can see how Collect is being more exacting as it's a nodeset.

A working relevance in both now would then be a non separated join that's not blank, join('' , ${input0}) != ''

Given WF is different does it need to be modified to behave like Collect?

@JenniferQ @gareth is there a reason for returning the value from the first repeat instead of showing an error? I think this should actually be caught by PyXForm when uploading to Central cc @Lindsay_Stevens_Au.

It seems to be by design. The line of code that’s resolving the first node has been there since the very beginning of web forms: https://github.com/getodk/web-forms/blob/522d5b5345f7e359c6489969ef3c312bb9a6c206/packages/xpath/src/evaluations/LocationPathEvaluation.ts#L719

It would be easy enough to identify ${} references to repeats, but working out if they are problematic or logically incorrect usages as nodesets may be quite tricky and/or fragile. I mean pyxform has a token parser but it’s doesn’t currently build the kind of XPath AST required for such a check. Maybe javarosa / validate could catch it though