hapijs/joi · error · AssertError

result.error.details[0].message

Error message

result.error.details[0].message

What it means

joi's assertPreferences(prefs) validates a preferences object against Schemas.preferences and throws an AssertError carrying the first validation message from result.error.details (lib/common.js:79). It means the preferences object you passed to .validate(prefs) / .match(prefs) etc. contains keys or values joi does not accept. The actual problem is inside AssertError.details — the message text names the offending key.

Source

Thrown at lib/common.js:79

};


exports.assertOptions = function (options, keys, name = 'Options') {

    Assert(options && typeof options === 'object' && !Array.isArray(options), 'Options must be of type object');
    const unknownKeys = Object.keys(options).filter((k) => !keys.includes(k));
    Assert(unknownKeys.length === 0, `${name} contain unknown keys: ${unknownKeys}`);
};


exports.checkPreferences = function (prefs) {

    Schemas = Schemas || require('./schemas');

    const result = Schemas.preferences.validate(prefs);

    if (result.error) {
        throw new AssertError([result.error.details[0].message]);
    }
};


exports.compare = function (a, b, operator) {

    switch (operator) {
        case '=': return a === b;
        case '>': return a > b;
        case '<': return a < b;
        case '>=': return a >= b;
        case '<=': return a <= b;
    }
};


exports.default = function (value, defaultValue) {

View on GitHub (pinned to 58ce83e919)

Solutions

  1. Read the message from the thrown error: catch it and inspect err.details / err.preferences — it names the offending key and expected type.
  2. Fix the offending preference key/value per that message, e.g. abortEarly must be a boolean.
  3. Validate prefs yourself first with Schemas.preferences.validate(prefs) during development to get the full details array instead of only the first message.
  4. If the preference comes from config/env, coerce types before passing (e.g. abortEarly: process.env.ABORT_EARLY !== 'false').

Example fix

// before
const result = schema.validate(value, { abortEarly: 'false', stripUnkown: true });
// after
const result = schema.validate(value, { abortEarly: false, stripUnknown: true });
Defensive patterns

Strategy: validation

Validate before calling

const Joi = require('joi');
const prefs = { abortEarly: false, stripUnknown: true };
const check = Joi.object({
  abortEarly: Joi.boolean(),
  stripUnknown: Joi.boolean(),
  errors: Joi.object(),
  wrap: Joi.object(),
  messages: Joi.object()
}).unknown(false).validate(prefs);
if (check.error) throw new Error('Bad joi preferences: ' + check.error.details.map(d => d.message).join('; '));

Type guard

function isValidPrefs(prefs) {
  return typeof prefs === 'object' && prefs !== null && !Array.isArray(prefs);
}

Try / catch

try {
  const result = schema.validate(value, prefs);
} catch (err) {
  if (err.name === 'AssertError' && Array.isArray(err.details)) {
    throw new Error('Invalid validate() preferences: ' + err.details.join('; '));
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling any API that accepts preferences with an invalid value, e.g. schema.validate(value, { abortEarly: 'yes' }) (string instead of boolean), { errors: { label: 42 } }, { wrap: { string: 'bad' } }, unknown keys like { stripUnkown: true } (typo), or passing a non-object.

Common situations: Typo'd preference keys (stripUnkown vs stripUnknown), wrong types after refactoring from string constants to enums, values copied from joi v13/v14 docs that were removed/renamed in newer versions, and preferences built dynamically from config/env where types are strings.

Related errors


AI-assisted analysis of hapijs/joi@58ce83e919 (2026-09-01). Data as JSON: /api/errors/2e3b37d39177b60c. Report an issue: GitHub.