Guides & concepts

Lifecycle hooks

Eight places to intervene, and the precedence rules between them.

HookFiresCan
onRequestBefore validationRewrite request or headers
onRequestValidatedAfter the body parsesObserve
onRequestValidationErrorBody or path failedSuppress with a fallback
onResponseBefore response validationReshape the body
onResponseValidatedAfter the body parsesObserve
onResponseValidationErrorResponse failedSuppress, or supply a fallback
onHttpErrorNon-ok statusSupply a fallback, or force a rethrow
onErrorAny escaping failureObserve

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.
  • rethrow beats fallback, in either order.
  • On response validation, a fallback outranks a suppress.
  • onRequestValidationError is the exception: the first suppress returns 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);
});