Summary
The "Agree" button rendered inside a human identification card passes the Identification PK as predictionId, but predictionId is routed to the backend field agreed_with_prediction_id — a FK to Classification, not Identification.
Location
ui/src/pages/occurrence-details/identification-card/human-identification.tsx:105
<Agree
...
agreeWith={{ predictionId: identification.id }} // ← identification.id is a human Identification PK
...
/>
Expected
When agreeing with a human identification, the UI should send:
agreeWith={{ identificationId: identification.id }}
so the backend stores the value in agreed_with_identification_id (FK to Identification).
Consequence
Depending on backend validation:
- FK validation fails → the Agree click errors silently or with a generic rejection.
- FK validation is lenient → the identification row ends up with a misrouted
agreed_with_prediction_id pointing at whatever Classification happens to share that PK (or orphaned).
Either way, the data on agreed_with_identification is never populated from this surface, which also means analytics / exports that rely on that FK (e.g. the agreed_with_user column added in PR #1214) will undercount transitive agreement chains.
Correct call sites (for reference)
These three call sites already pass both FKs correctly based on the current determination source:
ui/src/pages/occurrence-details/occurrence-details.tsx:176-179
ui/src/pages/occurrences/occurrence-actions.tsx:48-51
ui/src/pages/occurrences/occurrences-actions.tsx:73-76
And the sibling file machine-prediction.tsx:99,130 uses predictionId correctly because identification.id in that file refers to a Classification.
Fix
One-line change at human-identification.tsx:105:
- agreeWith={{ predictionId: identification.id }}
+ agreeWith={{ identificationId: identification.id }}
How to verify after fix
SELECT COUNT(*) FROM main_identification
WHERE agreed_with_identification_id IS NOT NULL AND withdrawn = FALSE;
should start growing as users click Agree on human identifications from the occurrence details page.
Discovered while reviewing PR #1214.
Summary
The "Agree" button rendered inside a human identification card passes the Identification PK as
predictionId, butpredictionIdis routed to the backend fieldagreed_with_prediction_id— a FK toClassification, notIdentification.Location
ui/src/pages/occurrence-details/identification-card/human-identification.tsx:105Expected
When agreeing with a human identification, the UI should send:
so the backend stores the value in
agreed_with_identification_id(FK toIdentification).Consequence
Depending on backend validation:
agreed_with_prediction_idpointing at whateverClassificationhappens to share that PK (or orphaned).Either way, the data on
agreed_with_identificationis never populated from this surface, which also means analytics / exports that rely on that FK (e.g. theagreed_with_usercolumn added in PR #1214) will undercount transitive agreement chains.Correct call sites (for reference)
These three call sites already pass both FKs correctly based on the current determination source:
ui/src/pages/occurrence-details/occurrence-details.tsx:176-179ui/src/pages/occurrences/occurrence-actions.tsx:48-51ui/src/pages/occurrences/occurrences-actions.tsx:73-76And the sibling file
machine-prediction.tsx:99,130usespredictionIdcorrectly becauseidentification.idin that file refers to aClassification.Fix
One-line change at
human-identification.tsx:105:How to verify after fix
should start growing as users click Agree on human identifications from the occurrence details page.
Discovered while reviewing PR #1214.