Объект ValidationError является центральной структурой,
через которую библиотека Joi сообщает о результатах неудачной валидации
данных. Он формируется при нарушении схемы и содержит детализированную
информацию о каждой обнаруженной ошибке, включая путь до поля, тип
нарушения, исходное значение и контекст проверки.
При неуспешной валидации возвращается объект ошибки, который обычно имеет следующий вид:
{
name: 'ValidationError',
isJoi: true,
message: '"username" is not allowed to be empty',
details: [ ... ],
_original: { ... }
}
Каждое поле имеет строго определённую роль и используется для диагностики и обработки ошибок.
message представляет собой агрегированное текстовое
описание ошибки. Оно формируется на основе первого или наиболее
значимого нарушения схемы.
Пример:
'"email" must be a valid email'
Особенности:
details — ключевая часть объекта
ValidationError. Это массив, содержащий полную информацию
обо всех нарушениях схемы.
Структура одного элемента массива:
{
message: '"age" must be greater than 18',
path: ['age'],
type: 'number.min',
context: {
limit: 18,
value: 16,
label: 'age',
key: 'age'
}
}
path описывает путь к проблемному значению внутри
объекта данных.
Примеры:
['email']['user', 'profile', 'age']Используется для:
type указывает тип нарушения правила валидации.
Примеры:
string.emptystring.emailnumber.minarray.minany.requiredТип ошибки позволяет программно обрабатывать разные классы ошибок без анализа текста сообщения.
context содержит дополнительные данные, использованные
при проверке правила.
Часто включает:
value — фактическое значениеlimit — ограничение (например, минимум или
максимум)key — имя поляlabel — отображаемое имя поляПример:
context: {
value: 10,
limit: 18,
key: 'age',
label: 'age'
}
_original содержит исходный объект данных, переданный на
валидацию.
{
username: '',
age: 16
}
Используется для:
isJoi — логический флаг, который позволяет отличить
ошибку Joi от других типов ошибок в приложении.
true
Часто применяется в middleware для фильтрации ошибок:
if (error.isJoi) {
// обработка ошибок валидации
}
Массив details позволяет получить сразу несколько ошибок
за одну проверку схемы.
Пример:
[
{ path: ['email'], type: 'string.email' },
{ path: ['password'], type: 'string.min' }
]
Это особенно важно при использовании режима
abortEarly: false, при котором валидация не останавливается
на первой ошибке.
Настройка:
Joi.object({
email: Joi.string().email(),
password: Joi.string().min(6)
}).validate(data, { abortEarly: false });
Результат:
detailsПри использовании messages() структура
ValidationError сохраняется, но текстовые поля
изменяются.
Joi.string().email().messages({
'string.email': 'Некорректный формат email'
});
В результате:
message изменяетсяdetails[].message также обновляетсяpath, type, context
остаётся неизменнойТипичный сценарий обработки:
app.post('/register', (req, res, next) => {
const schema = Joi.object({
email: Joi.string().email().required(),
password: Joi.string().min(6).required()
});
const { error } = schema.validate(req.body, { abortEarly: false });
if (error) {
return res.status(400).json({
errors: error.details.map(d => ({
field: d.path.join('.'),
message: d.message,
type: d.type
}))
});
}
next();
});
Здесь:
details преобразуется в формат APIpath используется как идентификатор поляtype помогает классифицировать ошибкуValidationError часто преобразуется в унифицированный формат:
const normalized = error.details.reduce((acc, err) => {
acc[err.path.join('.')] = err.message;
return acc;
}, {});
Результат:
{
email: '"email" must be a valid email',
password: '"password" length must be at least 6 characters long'
}
При сложных схемах path отражает полную иерархию:
{
user: {
profile: {
age: 15
}
}
}
Ошибка:
path: ['user', 'profile', 'age']
Это позволяет:
message — агрегированная строка всей ошибкиdetails[].message — конкретное сообщение для каждого
нарушенияПри множественных ошибках message обычно содержит первую
или наиболее значимую.
При использовании custom() или
external():
Joi.string().custom((value, helpers) => {
if (value === 'bad') {
return helpers.error('any.custom');
}
return value;
});
ValidationError будет содержать:
type: 'any.custom'contextdetailsValidationError может быть сериализован в JSON, но:
message, details,
_original)Error.stack не всегда включаетсяValidationError используется как:
Строгая структура details делает возможным
детерминированную обработку без парсинга текстовых сообщений.