XLSForm Constraint Examples (Copy & Paste)
XLSForm constraints validate an answer the moment it is entered using the constraint column, rejecting impossible values like a negative age or a future birth date. This guide gives you copy-paste constraint examples for the validations field surveys need most.
After adding a constraint, follow the XLSForm validation checklist to test visible paths, device behavior, and the exported result.
A constraint is a rule the answer must satisfy. If it fails, ODK shows your constraint_message and refuses to advance until the answer is fixed. This is how you keep bad data out of your dataset at the source — far more reliable than cleaning it later.
How does the constraint column work?
Add two columns to your survey sheet: constraint (the rule) and constraint_message (what the enumerator sees if it fails). Inside the rule, a single dot . refers to the current question's answer.
| type | name | label | constraint | constraint_message |
|---|---|---|---|---|
| integer | age | What is your age? | . >= 0 and . <= 120 | Age must be between 0 and 120 |
If someone types 250, ODK blocks it and shows "Age must be between 0 and 120". Below are ready-to-use rules for common cases — copy the constraint and constraint_message straight into your form.
Number range constraints
Keep numeric answers inside a plausible range:
| type | name | label | constraint | constraint_message |
|---|---|---|---|---|
| integer | age | Age of respondent | . >= 0 and . <= 120 | Age must be between 0 and 120 |
| integer | household | Household size | . >= 1 and . <= 30 | Household size must be 1 to 30 |
| decimal | price | Price paid (USD) | . >= 0 | Price cannot be negative |
Phone number and text constraints
Use regex() to enforce a text pattern, such as a 10-digit phone number:
| type | name | label | constraint | constraint_message |
|---|---|---|---|---|
| text | phone | Phone number | regex(. | '^[0-9]{10}$') |
| text | id_code | National ID | regex(. | '^[A-Z]{2}[0-9]{6}$') |
The string-length() function constrains length without a full pattern:
| type | name | label | constraint | constraint_message |
|---|---|---|---|---|
| text | pin | 4-digit PIN | string-length(.) = 4 | PIN must be exactly 4 characters |
Date constraints
Stop future dates or unrealistic ones using today():
| type | name | label | constraint | constraint_message |
|---|---|---|---|---|
| date | dob | Date of birth | . <= today() | Date of birth cannot be in the future |
| date | visit | Visit date | . <= today() and . >= '2026-01-01' | Visit date must be in 2026 up to today |
Cross-question constraints
A constraint can reference another answer with ${name} — for example, an end date that cannot precede a start date:
| type | name | label | constraint | constraint_message |
|---|---|---|---|---|
| date | start_date | Start date | ||
| date | end_date | End date | . >= ${start_date} | End date must be on or after the start date |
Constraints only run on questions that are actually shown. If a question is hidden by skip logic, its constraint never fires — which is exactly what you want, but worth remembering when a rule seems to be ignored.
Select-question constraints
Limit how many options a respondent may choose in a select_multiple question with count-selected():
| type | name | label | constraint | constraint_message |
|---|---|---|---|---|
| select_multiple symptoms | symptoms | Select up to 3 symptoms | count-selected(.) <= 3 | Choose no more than 3 symptoms |
You do not have to memorize this syntax. In LooprAI Workspace, describe the rule in plain English — "age must be 18 to 65" — and it writes the correct constraint and message for you, then validates the whole form.
Why constraints matter in the field
Constraints are your first and cheapest line of data-quality defense. They block impossible values before they enter the dataset, cut hours of post-survey cleaning, and reduce the back-and-forth of re-contacting respondents to fix errors. Combined with an audit log, validated answers give you data you can trust on day one rather than at endline.
Build my first form freeNext: How to Add Skip Logic in XLSForm →
Frequently Asked Questions
What is a constraint in XLSForm?
A constraint is a validation rule in the constraint column that an answer must satisfy. If the answer fails the rule, ODK displays the constraint_message and refuses to advance until it is corrected, keeping impossible values out of your data at the source.
How do I limit a number range in XLSForm?
Use the dot to reference the current answer and combine bounds with 'and'. For example, the constraint . >= 0 and . <= 120 on an age question rejects any value below 0 or above 120. Pair it with a clear constraint_message.
How do I validate a phone number in XLSForm?
Use the regex() function in the constraint column. The rule regex(., '^[0-9]{10}$') requires exactly ten digits and rejects letters or wrong lengths. Adjust the pattern to match your country's phone format.
How do I stop future dates in XLSForm?
Compare the date answer to today() in the constraint column. The rule . <= today() blocks any date later than the current day, which is ideal for fields like date of birth or interview date that cannot be in the future.
Can an XLSForm constraint reference another question?
Yes. Use ${question_name} inside the constraint to compare against another answer. For example, an end-date constraint of . >= ${start_date} ensures the end date is on or after the start date entered earlier in the form.
No Credit Card Required
Build the form first. Add hosting when you need it.
Start free with LooprAI, then deploy a managed ODK Central server or run DataSnap checks when your project is ready.
Hundreds of users trust SurveyLoopr