next-safe-action Middleware
Quick Start
How Middleware Works
.use()adds middleware to the chain — you can call it multiple times- Each
.use()returns a new client instance (immutable chain) - Middleware executes top-to-bottom (in the order added)
- Results flow bottom-to-top (the deepest middleware/action resolves first)
- Context is accumulated via
next({ ctx })— each level's ctx is deep-merged with the previous
use() Middleware Function Signature
useValidated() — Post-Validation Middleware
.useValidated() registers middleware that runs after input validation, giving access to typed parsedInput. Default to use() — only use useValidated() when middleware logic depends on validated input.
Execution Order
Both middleware stacks follow the onion model: code before next() runs top-to-bottom, code after next() unwinds bottom-to-top.
use() vs useValidated()
useValidated() Middleware Function Signature
Chaining Rules
- Must call
.inputSchema()or.bindArgsSchemas()before.useValidated() - Cannot call
.inputSchema()or.bindArgsSchemas()after.useValidated() - Cannot call
.use()after.useValidated() - Can chain multiple
.useValidated()calls
Schema Transforms
useValidated() sees the transformed value in parsedInput, while clientInput retains the original:
Context in Error Callbacks
- Context set by
use()middleware is always available inonError/onSettledcallbacks. - Context set by
useValidated()middleware is optional (may beundefined) — if validation fails,useValidated()never runs, so its context additions are missing.
Supporting Docs
- Authentication & authorization patterns
- Logging & monitoring middleware
- Standalone reusable middleware with createMiddleware() and createValidatedMiddleware()


