Enrollment AGE attribute unavailable or evaluated as null when program rules are revalidated on event completion in 2.42

Hello,

After upgrading from DHIS2 2.40 to 2.42, program rules that use an enrollment-level tracked entity attribute with value type AGE to assign Age category behave differently during event entry and event completion.

While editing the event, the program rules are evaluated correctly and automatically assign the expected age category. However, when the user attempts to complete the event, validation fails for events where the AGE attribute contains a value.

Events for which the AGE attribute is empty can be completed successfully.

This appears to be a regression from DHIS2 2.40, where the same program rules worked correctly.

Program configuration

The Tracker program contains:

  • An enrollment-level tracked entity attribute with value type AGE
  • A first program stage that is non-repeatable
  • A data element named Age category
  • One program rule for each age category

The available age categories are:

  • 0–4 years
  • 5–9 years
  • 10–14 years
  • 15–19 years
  • 20–44 years
  • 45–64 years
  • 65 years and above
  • Unknown age

The age-category rules use d2:yearsBetween() to calculate the age at the event date, based on the AGE attribute and the event date.

Example condition for the 0–4 years category:

d2:hasValue(#{TEA age}) &&
d2:yearsBetween(#{TEA age}, V{event_date}) < 5

The other known-age categories use the same pattern, with the relevant lower and upper limits.

Example condition for the Unknown age category:

!d2:hasValue(#{TEA age})

Each rule assigns the corresponding option or value to the Age category data element.

Steps to reproduce

  1. Create or open an enrollment in the Tracker program.
  2. Enter a value in the tracked entity attribute with value type AGE.
  3. Open the first, non-repeatable program-stage event.
  4. Enter or confirm the event date.
  5. Observe that the Age category data element is populated correctly by the relevant program rule.
  6. Attempt to complete the event.

Actual behaviour

The age-category program rule works correctly while the event is being edited.

However, when the event is completed, validation fails for events where the AGE attribute contains a value.

The behaviour is consistent with the rule engine evaluating the AGE attribute as empty or unavailable during completion validation. As a result, the previously assigned age category appears to become inconsistent with the program-rule evaluation performed at completion.

Events where the AGE attribute is genuinely empty do not produce the error and can be completed. In those cases, the Unknown age rule is evaluated as expected.

Expected behaviour

The tracked entity attribute should remain available to the program-rule engine during event completion validation.

The result of:

d2:yearsBetween(#{TEA age}, V{event_date})

should be evaluated consistently:

  • while editing the event; and
  • when validating the event during completion.

An event for which the correct age category has already been assigned should complete without a validation error.

Regression

The same Tracker program and program-rule configuration worked correctly in DHIS2 2.40 in the Tracker Capture app

The issue appeared after upgrading to DHIS2 2.42.4 and using the Capture app

Reproducibility

The issue has been reproduced in several independent DHIS2 2.42 environments:

  • the official DHIS2 demo server (2.42.5.1) with Capture app v106.7.4;
  • a cloud-hosted development server (2.42.4) with Capture app v105.7.0, v106.2.2 & v106.7.5
  • a local Docker installation (2.425.1) with Capture app v106.2.2

This suggests that the issue is not specific to one database, server configuration, or hosting environment.

Additional observations

  • The program rules evaluate correctly during interactive event entry.
  • The error occurs specifically when completing the event.
  • Events with an empty AGE attribute can be completed.
  • Updating the rule assigning Unknown age to HIDE the data element Age category instead of assigning a value solves the error on validation (but we don’t want to loose the Unknown age value and it’s still a bug if TEA cannot be accessed by the rule engine during validation on completion).
  • The issue may therefore be related either to:
    • the availability of enrollment-level attributes during completion validation; or
    • the handling of AGE-type attributes when d2:yearsBetween() is re-evaluated during completion.

Environment

  • DHIS2 versions tested: 2.42.4 & 2.42.5.1
  • Previous working version: 2.40.4.1
  • Capture app versions tested: 105.7.0, 106.2.2, 106.7.4 & 106.7.5

Thank you @KathyBuelens for the detailed post. I’ve triaged the post and was asked to create a bug ticket so I created one on your behalf here: Jira

Thank you! :folded_hands:

Thanks @Gassim!

Hello @KathyBuelens!
I need to ask a couple of follow-up questions to figure this one out :sweat_smile:

I’m assuming the validation error you get comes from a program rule – could you give me a rough description of what its program rule condition looks like?

Also, a question on the timing of the error: Suppose you save the event without completing it, and then go back to it in edit mode. Does selecting the “Complete event”-checkbox trigger the validation error, or does it occur only after you also click the Save-button?

:detective: :folded_hands:

Hello Tony,

It’s a bug that has been reported in jira (Jira) and a fix should be provided soon. Basically, the issue is linked to program rules using a tracked entity attribute in the condition and more specifically when !d2:hasValue(TEA) triggers an Assign action. It looks like the rule engine on completion does not have access anymore to tracked entity attribute, hence treats any condition with TEA being null as true and throws an error on completion because there is a mismatch whith what has been correctly assigned while in the form and the output calculated during completion validation. Save only doesn not trigger the error. Another example would be rules assigning nutrition z-score when Sex is recorded in a tracked entity attribute. While in the form, the z-score would be calculated correctly but on completion validation, sex would be considered as missing, hence the d2:fucntion would fall back to the default value which is female. The rule engine would throw an error for all male patients.
Kind regards,
Kathy