Universal Field Validator

@UVEXISTS

@UVEXISTS is a REDCap action tag that checks a value is already saved in the project, such as a specimen ID registered on another form or an existing record ID.

REDCap can check that a value looks right, but not that it refers to something real. A lab result can name a specimen ID that was never registered, and a follow-up form can point to a participant record that does not exist. @UVEXISTS checks, as the value is entered, that it is already saved in the project: a record ID, or a value of another field such as the specimen ID on the collection form.

Syntax

@UVEXISTS=record

@UVEXISTS=[specimen_id]

@UVEXISTS={"in":"[specimen_id]","event":"enrolment_arm_1","scope":"dag",
           "match":{"site_code":"[site]"},
           "message":"Register the specimen on the collection form first.",
           "blockSave":"hard"}
KeyMeaning
inrecord (a record ID of this project), or one field reference such as [specimen_id] (a value saved in that field, in any record)
eventLook in one event only, by its unique event name
scopeproject (default), dag (records of the same Data Access Group) or event (the event of the entry being checked)
matchLook only at saved entries whose target field equals a field of this record, e.g. {"site_code":"[site]"}; up to 5 pairs
returnCopy fields of the entry found into fields of this form, e.g. {"lab_site":"[result_site]"}; up to 10 pairs (see below)
whereA condition the entry found must meet, e.g. "[consent]='1' and [status]<>'3'"; up to 10 fields (see below)
whereMessageThe message staff see when the value is saved, but not in an entry that meets where
surveystrue to check on surveys too (off by default)
projectLook in another project on the same server, by project id or by an alias set in this project's module settings; that project must agree (see below)
caseSensitivetrue compares letter case exactly, in the lookup and in when (off by default: sp-1 finds SP-1)
message, blockSave, whenAs for the other tags

Field types

Text, dropdown, radio and SQL fields. The field searched in, and each pair of match fields, must be stored the same way: two dates, two datetimes to the minute, two datetimes to the second, two times of the same precision, or neither a date nor a time, because dates are compared as stored. Two fields that hold numbers must use the same decimal mark.

What is checked, and when

Looking in another project

@UVEXISTS={"in":"[specimen_id]","project":"lab","match":{"site_code":"[site]"}}

Copying fields of the entry found

With return the lookup works like a spreadsheet VLOOKUP and copies fields of the entry it finds into fields of this form. Each key is a field of the entry found and each value a field here, the same way round as match. record copies the record ID of the entry found. A rule takes up to 10 pairs.

@UVEXISTS={"in":"[specimen_id]",
           "return":{"lab_site":"[result_site]","coll_date":"[result_coll_date]"}}

@UVEXISTS={"in":"[specimen_id]",
           "return":{"record":"[source_record]","coll_date":"[result_coll_date]"}}

@UVEXISTS={"in":"record","event":"enrolment_arm_1","return":{"enrol_date":"[mother_enrol_date]"}}

@UVEXISTS={"in":"[specimen_id]","project":"lab","return":{"site_code":"[result_site]"}}

The first rule, on result_specimen_id, fills the site and collection date of the registered specimen. The second also copies the record the specimen was registered in. The third, on mother_record_id, reads the mother's enrolment date from the enrolment event, and the fourth copies from the lab project when its agreement lets this project copy site_code. For SP-1, registered in record 12 with lab_site 2 and coll_date 2026-03-01, the first rule writes 2 into result_site and, for a result_coll_date shown as D-M-Y, 01-03-2026.

Which values are copied

What a field here can take

The value is copied as REDCap stores it, so the field here must be able to hold every value the field there can.

Field thereField here
Any valueA Text field without validation, or a Notes field
Dropdown, radio, yes/no, true/falseA choice field that has each of its codes, or a Text field without validation (it gets the code)
A date, datetime or timeA Text field with the same kind of date or time; the order it shows the date in may differ
A numberA Text field with number validation and the same decimal mark. When the field here fixes its decimal places (integer, number_1dp, number_2dp and so on), the field there must fix the same number of them, because number_2dp takes exactly two places and 7.5 would fail it
Any other validationA Text field with the same validation

Rights, surveys and when the values are written

Copying from another project

The searched project lists the fields others may copy apart from the fields they may search, under "Fields of this project whose values it may copy" (record for its record ID), and only for the choice "Only users who have rights". A rule that copies a field not on that list gets the same setup error as any other refusal there. A refusal that would describe how that project is built (a copied field on a repeating form or missing from an event, an event that repeats) gives one message instead, "project N cannot give the values "return" asks for". A choice field here that lacks a code of the field there is refused without naming the code. The page and the save check the user's rights in both projects: here the forms of this field and of each match field here, there the forms of the fields searched and copied.

Only entries that meet conditions

With where the value must be saved in an entry that meets a condition on that entry. The condition takes the language of when: one comparison, or several joined with and, or and not, with parentheses and keywords in any letter case.

@UVEXISTS={"in":"[specimen_id]","project":"lab",
           "where":"[consent]='1' and ([status]<>'3' or [withdraw_date]>[coll_date])",
           "whereMessage":"This specimen is registered, but not consented or withdrawn."}

@UVEXISTS={"in":"[kit_number]","where":"[kit_check(2)]='1' and not([kit_check(4)]='1')"}

@UVEXISTS={"in":"record","project":"screening","event":"screening_arm_1","where":"[eligible]='1'"}
KeyAsksIts fields are
whenDoes the rule apply to this record at all?fields of this record
matchDoes the entry found hold the same value as a field of this record? a field there, paired with a field here
whereDoes the entry found meet fixed conditions?fields of the entry found

Audit

The post-save audit logs a violation as type: exists with reason not-found, or filtered for a value saved only in entries that fail where, and the Validation scan reports it. Saving the form that holds a match field checks the lookup again. The scan reads the searched field once per rule per scan request and checks every record against it. A lookup that could not be completed is reported as a rule problem, never as a pass. A scan confined to one Data Access Group reports a rule that looks across groups as not evaluated, because a value saved only in another group would read as not found. A durable scan with @UVEXISTS rules claims coverage through its change fence only when no record changed during the run.