I’m working on an integration where ONA(ODK) form submissions are pushed into DHIS2 as events using the Tracker Import API. The form has a farmer photo (valueType=IMAGE data element).
The challenge I’m facing:
In the database, each event correctly stores a different fileResource UID for the IMAGE data element.
In the fileResource table, both fileResources exist with domain=DATA_VALUE and contentType=image/jpeg.
However, in the Capture app, both events show the same photo, even though the fileResource UIDs are different.
What I’ve tested
Uploaded photos through Capture app → images displayed correctly per event.
Uploaded photos through Postman → DHIS2 accepts them (/api/fileResources → returns 202 Accepted).
Uploaded photos through my Python script → also returns 202 Accepted, different fileResource UIDs created.
After import, the fileresource entries are created, and I can see storageStatus progress from PENDING → STORED.
Suspicions
When posting via API, DHIS2 may not be creating/associating the image entry immediately, so the Capture app might be reusing a cached/first available image.
Or possibly, attaching the fileResource UID to a dataValue right after upload (while still PENDING) leads to mis-rendering in Capture.
In my script, I now poll /api/fileResources/{uid} until storageStatus=STORED before using it in event payloads.
My Questions
Has anyone else faced this issue where different events (with different fileResource UIDs) show the same image in the Capture app?
Is there a recommended way to handle fileResource upload → event dataValue association to avoid this?
Should we always wait until storageStatus=STORED before linking the UID to an event?
Could the difference be because Capture uploads directly vs API upload (e.g., how multipart/form-data is handled)?
Environment
DHIS2 v2.42 (Tracker Import API)
Capture app (latest release)
Integration: Python script posting to /api/fileResources then /api/tracker
Any advice or best practices on this would be greatly appreciated.
Great set of questions — this is a fairly common pain point when working with file resources in DHIS2 (especially with images in Capture vs API uploads). Let me break them down one by one:
1. Has anyone else faced this issue where different events (with different fileResource UIDs) show the same image in the Capture app?
Yes, this happens sometimes. A few known causes:
FileResource not yet stored: The UID is created immediately after upload, but until its storageStatus=STORED, it’s not fully processed. If you link it prematurely, you can end up with a mismatch or even a reused cached image.
Browser / app caching: The Capture app often aggressively caches images. If multiple events point to “in-progress” or incorrectly referenced FileResource UIDs, it can display the same image.
Asynchronous sync: In offline/online scenarios, Capture might show placeholders or the wrong file temporarily until the sync cycle completes.
2. Is there a recommended way to handle fileResource upload → event dataValue association to avoid this?
Yes:
Upload the file via /fileResources (or Capture’s built-in mechanism).
Poll the FileResource until storageStatus=STORED.
Only then update the event’s dataValue with the fileResource UID.
This ensures the event is pointing at a finalized, retrievable file rather than a transient one.
3. Should we always wait until storageStatus=STORED before linking the UID to an event?
Best practice: yes.
If you don’t wait, you risk:
Broken images in Capture.
Multiple events pointing to the same “unstored” placeholder resource.
Sync conflicts between API uploads and Capture.
4. Could the difference be because Capture uploads directly vs API upload (e.g., how multipart/form-data is handled)?
Exactly. Capture’s flow:
Capture app uploads the image → gets a UID immediately.
It then links that UID to the event in the same sync transaction.
The DHIS2 backend finishes storing the file asynchronously.
API/manual flow:
If you POST multipart/form-data directly to /fileResources, you might link the UID before it’s ready (unless you explicitly check storageStatus).
Different clients handle multipart encoding and caching differently, so Capture might be hiding some of that complexity.
Summary / Recommendation:
Always check for storageStatus=STORED before linking a FileResource to an event.
Be careful with Capture caching — sometimes you need to clear cache / resync to see the correct image.
If doing custom API uploads, mimic Capture’s sequence (upload → wait for STORED → link to event).