Guides & concepts
Lifecycle hooks
Eight places to intervene, and the precedence rules between them.
| Hook | Fires | Can |
|---|---|---|
| onRequest | Before validation | Rewrite request or headers |
| onRequestValidated | After the body parses | Observe |
| onRequestValidationError | Body or path failed | Suppress with a fallback |
| onResponse | Before response validation | Reshape the body |
| onResponseValidated | After the body parses | Observe |
| onResponseValidationError | Response failed | Suppress, or supply a fallback |
| onHttpError | Non-ok status | Supply a fallback, or force a rethrow |
| onError | Any escaping failure | Observe |
Precedence
- Every hook runs — the loops do not break, so telemetry still fires after another hook decided.
- The last fallback wins; a hook returning nothing does not clear an earlier one.
rethrowbeatsfallback, in either order.- On response validation, a fallback outranks a suppress.
onRequestValidationErroris the exception: the firstsuppressreturns immediately.
Path failures share the request hook
A path-parameter failure reaches onRequestValidationError with source: 'path'. There is no ninth hook: both mean the caller sent bad input, so they share one extension point while keeping distinct error tags.
ep.onRequestValidationError((ctx) => {
if (ctx.source === 'path') return { suppress: true, fallback: EMPTY };
report(ctx.failure.issues);
});