Request Validation Plugin
Request Validation Plugin validates requests against your contract before they are sent to the server. This is useful when your application relies on server-side validation.
Setup
import { RequestValidationLinkPlugin } from '@orpc/contract/plugins'
const link = new RPCLink({
plugins: [
new RequestValidationLinkPlugin(contract),
],
})INFO
If you do not have a contract, you can use a unlazied router instead.
INFO
The link can be any supported oRPC link, such as RPCLink, OpenAPILink, or a custom one.
Forward Validated Input
By default, the plugin does not reuse validated input for the rest of the request. Some schemas transform input in ways that can cause server-side validation to fail. If your schemas do not do that, set forwardValidatedInput to true.
const link = new RPCLink({
plugins: [
new RequestValidationLinkPlugin(contract, {
forwardValidatedInput: true,
}),
],
})Custom Validation Errors
If you have already customized validation errors on the server, you can use interceptors to catch and map the validation errors thrown by this plugin so they match your server-side errors.
import { ORPCError } from '@orpc/client'
import { ValidationError } from '@orpc/contract'
const link = new RPCLink({
plugins: [
new RequestValidationLinkPlugin(contract),
],
interceptors: [
async ({ next }) => {
try {
return await next()
}
catch (error) {
if (
error instanceof ORPCError
&& error.code === 'BAD_REQUEST'
&& error.cause instanceof ValidationError
) {
throw new CustomInputValidationError(error.cause.issues)
}
throw error
}
}
]
})Form Validation
You can pair this plugin with Form Data Helpers to avoid heavier form validation libraries and keep your contract as the single source of truth on both the client and server.
import { getIssueMessage, parseFormData } from '@orpc/openapi/helpers'
export function ContactForm() {
const [error, setError] = useState()
const handleSubmit = async (form: FormData) => {
try {
const output = await client.someProcedure(parseFormData(form))
console.log(output)
}
catch (error) {
setError(error)
}
}
return (
<form action={handleSubmit}>
<input name="user[name]" type="text" />
<span>{getIssueMessage(error, 'user[name]')}</span>
<input name="user[emails][]" type="email" />
<span>{getIssueMessage(error, 'user[emails][]')}</span>
<button type="submit">Submit</button>
</form>
)
}Learn More
For implementation details, see the source code.

