如何在Hapi框架中处理Joi验证错误?
I have the following Hapi route configuration with Joi validation:
const routeConfig = { method: 'POST', path: '/user', config: { validate: { payload: { firstName: Joi.string().required(), } }, handler } }
When I don't pass the firstName parameter, it throws this error:
{ "statusCode": 400, "error": "Bad Request", "message": "child \"firstName\" fails because [\"firstName\" is required]", "validation": { "source": "payload", "keys": [ "firstName" ] } }
My current handler code includes a try/catch block, but I'm unsure how to properly catch and handle this validation error in the catch section:
const handler = async(request, reply) => { try { const payload = request.payload const createUser = await User.create(payload) let token = Helpers.createJwt(createUser) reply({ success: true, message: 'User created successFully', token }) } catch(err) { // Need to handle the validation error here // Like checking if it's the required firstName error and returning custom response } }
How can I correctly catch and handle this validation error in the catch block?
Great question! Hapi uses the Boom library under the hood for HTTP errors (including Joi validation failures), so you can leverage its built-in properties to identify and handle these errors cleanly. Here's how to adjust your catch block:
Step 1: Identify the Boom validation error
Boom errors have an isBoom property set to true, and validation failures will always have a statusCode of 400 along with a validation object in the error details.
Step 2: Build your custom error response
You can either extract details from the existing error or return a fully custom message like you wanted. Here's the updated handler code:
const handler = async(request, reply) => { try { const payload = request.payload const createUser = await User.create(payload) let token = Helpers.createJwt(createUser) reply({ success: true, message: 'User created successFully', token }) } catch(err) { // Check if this is a Hapi/Joi validation error if (err.isBoom && err.statusCode === 400 && err.data?.validation) { // Extract the first missing/invalid field (you can loop through all if needed) const missingField = err.data.validation.keys[0]; reply({ error: `${missingField} is required`, message: 'Signup unsuccessful' }).code(400); // Always set the correct HTTP status code } else { // Handle other unexpected errors (e.g., database issues) reply({ error: 'Internal server error', message: 'Something went wrong during signup' }).code(500); } } }
Key details to note:
err.isBoom: Confirms this is a standardized Hapi HTTP errorerr.statusCode === 400: Ensures we're targeting "Bad Request" errors (the type validation failures fall into)err.data?.validation: Contains Joi's validation details, including thekeysarray of problematic fields- Setting the status code with
.code()keeps your API REST-compliant, which is important for client-side error handling
If you want to handle all validation errors generically instead of targeting just firstName, you can even use the pre-built message from err.message, but your custom response works perfectly for a focused user experience.
内容的提问来源于stack exchange,提问作者Ashish Choudhary

