mjmlio/mjml · error · ValidationError
ValidationError: \n ${errors.map((e) => e.formattedMessage).
Error message
ValidationError: \n ${errors.map((e) => e.formattedMessage).join('\n')} What it means
In strict validation mode, mjml2html runs MJMLValidator over the parsed document and, if any validation errors are found, throws a ValidationError whose message lists each error's formattedMessage. Unlike loose/skip modes which collect warnings, strict mode fails fast so invalid MJML never renders.
Source
Thrown at packages/mjml-core/src/index.js:650
lang: get(mjml, 'attributes.lang') || 'und',
dir: get(mjml, 'attributes.dir') || 'auto',
}
const validatorOptions = {
components,
dependencies,
initializeType,
}
switch (validationLevel) {
case 'skip':
break
case 'strict':
errors = MJMLValidator(mjml, validatorOptions)
if (errors.length > 0) {
throw new ValidationError(
`ValidationError: \n ${errors
.map((e) => e.formattedMessage)
.join('\n')}`,
errors,
)
}
break
case 'soft':
default:
errors = MJMLValidator(mjml, validatorOptions)
break
}
const mjBody = find(mjml.children, { tagName: 'mj-body' })
const mjHead = find(mjml.children, { tagName: 'mj-head' })
const mjOutsideRaws = filter(mjml.children, { tagName: 'mj-raw' })
View on GitHub (pinned to 6c01d35af5)
Solutions
- Fix each listed formattedMessage: correct the tag name, attribute, or structure at the given line in your MJML.
- Register custom components with the validator so unknown-tag errors disappear (registerMJElement/component registration).
- Set validationLevel to 'soft' (warn only) or 'skip' if you intentionally render non-strict documents.
- Compare against MJML docs for deprecated components after a version upgrade.
Example fix
// before
mjml2html(mjml, { validationLevel: 'strict' }) // <mj-foo> unknown
// after
mjml2html(mjml.replace('<mj-foo>', '<mj-text>'), { validationLevel: 'strict' })
// or: { validationLevel: 'soft' } to downgrade to warnings Defensive patterns
Strategy: try-catch
Validate before calling
import { MJMLValidator } from 'mjml-validator'
const errs = MJMLValidator(require('mjml-parser-xml')(mjmlString))
if (errs.length) console.warn('MJML validation issues:', errs.map(e => e.formattedMessage)) Try / catch
import { ValidationError } from 'mjml-core'
try {
return mjml2html(src, { validationLevel: 'strict' })
} catch (e) {
if (e instanceof ValidationError) {
console.error('MJML validation failed:', e.errors.map(x => x.formattedMessage).join('\n'))
} else throw e
} Prevention
- Run validation as a pre-commit/CI step on all templates.
- Register custom components before validating/rendering.
- Pin mjml versions and re-validate templates after upgrades.
When it happens
Trigger: Calling mjml2html with validationLevel: 'strict' on a document containing any validation error, e.g. unknown component tags like <mj-foo>, invalid attribute values, or components in forbidden parents.
Common situations: CI pipelines configured with strict validation that newly introduced an unsupported component or attribute typo; upgrading mjml where a component/attribute was deprecated; custom components registered under a name the validator does not know.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- No type found for ${typeConfig}
- e.formattedMessage (compiled MJML errors printed via console
- dependency "tag" must be of type string
- "dependencies" must be an object.
- "dependencies" option should be provided to mjml validator
AI-assisted analysis of mjmlio/mjml@6c01d35af5 (2026-09-02).
Data as JSON: /api/errors/32a9272ff02db5b5.
Report an issue: GitHub.