noop and exception
Every lesson since lesson 3 has written on_fail="noop" without explaining it. This part is the eight choices that argument accepts, starting with the two that change nothing about the value.
from guardrails import OnFailAction
print(sorted(action.value for action in OnFailAction))Six of those you set yourself. custom is set for you when you pass a function instead of a name, which is lesson 12. reask and fix_reask need a model to ask, so they wait until lesson 16.
noop
from guardrails import Guard
from guardrails_ai.valid_length import ValidLength
desk = Guard().use(ValidLength(min=1, max=20, on_fail="noop"))
outcome = desk.validate("Order 8821 is running late and arrives Friday.")
print(outcome.validation_passed)
print(outcome.validated_output)
print(desk.history.last.status)The value comes back untouched, the verdict is False, and the call is recorded as a failure. Nothing downstream is protected, which sounds useless until you are adding a rule to a desk that is already live.
That is what noop is for. Turn a new rule on with noop, leave it for a week, count how often it fires on real traffic, and only then decide whether it should be allowed to change anything.
exception
desk = Guard().use(ValidLength(min=1, max=20, on_fail="exception"))
try:
desk.validate("Order 8821 is running late and arrives Friday.")
except Exception as error:
print(type(error).__name__)
print(error)
print(desk.history.last.status)Nothing comes back at all, and the call is still in the history, so a failure that stops your program is as inspectable as one that does not. This is the action a validator gets when you do not set one, which lesson 3 found the hard way.
Guardrails' own Error and Remediation page recommends exceptions once an application gets complicated, on the grounds that they let you route different failures down different paths instead of quietly returning a repaired string that nobody checks.
Choosing between them
| You want to | Use |
|---|---|
| Measure a new rule without changing behaviour | noop |
| Stop the request and handle it in your own code | exception |
| Return something safe to the user | fix, lesson 10 |
| Return nothing rather than something wrong | refrain, lesson 11 |
| Ask the model to do better | reask, lesson 16 |
- Set the same validator to
noopand thenexceptionand printdesk.history.last.statusafter each. It isfailboth times. - Catch the exception and print
desk.history.last.validator_logs[0].validation_result.error_message. The sentence in the exception came from there. - Add a second validator that passes, and confirm
exceptionon the first one still stops the run.
This is what real progress feels like.