Briefly: every input component on a screen has a Validate Input section holding a formula that must evaluate to true, plus the error message shown when it does not. It fires when the user clicks Next or Finish, never while they type and never when they click Previous. For anything that compares two fields, use a Decision after the screen instead, because the built-in validation is designed around one input at a time.
Where the setting lives and what the formula means
Open a Text, Number, Date, Picklist or similar component in the screen editor and expand the input validation section. You write a formula that returns true when the value is acceptable. This catches people out: the formula describes the valid state, not the error state. A formula that returns true for bad input passes bad input.
Inside the formula, reference the component’s own value with its API name. A length check on a text input looks like this:
LEN({!Employee_Code}) = 6
Numeric ranges work the same way, and BLANKVALUE is worth reaching for because an untouched optional field is null, and comparisons against null are not always what you expect:
AND(
BLANKVALUE({!Discount_Percent}, 0) >= 0,
BLANKVALUE({!Discount_Percent}, 0) <= 40
)
It only fires on Next, and that is a design constraint
The validation runs when the user tries to leave the screen forwards. Everything on the screen is checked at once, so a user who got three fields wrong sees three messages together. Clicking Previous skips validation entirely, which is correct behaviour and occasionally surprising if you were relying on validation to populate something.
One consequence that costs people an afternoon: a component hidden by a conditional visibility rule is not validated, and its value is not passed on. If you make a required field invisible, the flow does not complain, it just proceeds with nothing in that variable. Test every visibility combination, including the ones you did not build first.
Cross-field rules belong in a Decision
The natural thing to want is “End Date must be after Start Date” on the End Date component. Do not build it there. Component validation is scoped to one input, and rules that reach across the screen are fragile and hard for the next person to find.
The pattern that holds up: screen, then a Decision testing the combination, with the failing outcome looping back to the same screen. Put a Display Text component at the top of that screen bound to an error variable, with its component visibility set to show only when the variable is not blank. Assign the message before you loop back. The user lands on the screen they already filled in, with their values intact and a specific explanation above the fields.
It is more elements than a formula, and it is the version that still works when the rule grows a third condition next quarter.
Custom components validate themselves
The built-in validation section does not appear on a custom Lightning web component. The component has to do the work, by exposing a validate() method that the flow runtime calls when the user clicks Next:
@api
validate() {
if (this.value && this.value.length === 6) {
return { isValid: true };
}
return {
isValid: false,
errorMessage: 'Enter the six-character employee code from your badge.'
};
}
Return isValid: false and the flow stays on the screen and shows your message. Without this method the runtime has no way to know the component is unhappy, which is why a custom component that looks validated in isolation lets anything through inside a flow.
Write the message for the person reading it
The error text is rendered next to the field and announced by screen readers, so it is doing accessibility work whether you thought about it or not. Three rules:
- Say what correct looks like. “Enter a date on or after today”, not “Invalid date”.
- Do not describe position or colour. “The field highlighted in red” means nothing to a screen reader user.
- Keep the field label descriptive on its own, because the message is read in relation to it.
Validation on a screen catches the input. It does not replace a validation rule, which is what stops the same bad value arriving through the API.
Frequently asked
Can I validate against a record in the database? Not in the formula, which is evaluated client-side. Query first and pass the value into a flow variable the formula can reference, or do the check in a Decision after the screen.
Does validation run on Finish? Yes. Finish is a forward move, so the last screen validates before the flow completes.
Why is my message not showing? Usually the formula returns true for the bad case. Invert it and retest, and remember that a null value fails many comparisons silently.
