mjmlio/mjml · error · Error
No type found for ${typeConfig}
Error message
No type found for ${typeConfig} What it means
initializeType resolves a type config string (e.g. used by mjml attribute validators) against a list of known type constructors by matching each type's matcher regex. When no registered constructor's matcher matches the given typeConfig string, it throws 'No type found for <typeConfig>'. This means the requested type name is not part of mjml-core's built-in type registry.
Source
Thrown at packages/mjml-core/src/types/type.js:16
import { some, find } from 'lodash'
import typesConstructors from './index'
// Avoid recreate existing types
export const types = {}
export const initializeType = (typeConfig) => {
if (types[typeConfig]) {
return types[typeConfig]
}
const { typeConstructor } =
find(typesConstructors, (type) => !!typeConfig.match(type.matcher)) || {}
if (!typeConstructor) {
throw new Error(`No type found for ${typeConfig}`)
}
types[typeConfig] = typeConstructor(typeConfig)
return types[typeConfig]
}
export default class Type {
constructor(value) {
this.value = value
}
isValid() {
return some(this.matchers, (matcher) => `${this.value}`.match(matcher))
}
getErrorMessage() {
if (this.isValid()) {View on GitHub (pinned to 6c01d35af5)
Solutions
- Check the message's typeConfig value and fix the typo / use a supported type (string, color, unit, enum, etc.).
- If you need a custom type, register a matching type constructor in the types registry before initializing elements.
- Grep your component definitions for the offending type string and correct all occurrences.
- Verify against the mjml-core version in use that the type still exists.
Example fix
// before
attributes: { color: { type: 'colour' } }
// after
attributes: { color: { type: 'color' } } Defensive patterns
Strategy: type-guard
Validate before calling
const SUPPORTED = ['string', 'color', 'unit', 'enum', 'boolean', 'number'];
function checkAttrTypes(componentDef) {
for (const [name, a] of Object.entries(componentDef.attributes || {})) {
if (a.type && !SUPPORTED.includes(a.type)) throw new Error(`Unsupported attribute type '${a.type}' on ${name}`);
}
} Type guard
function hasKnownType(attr) {
return typeof attr === 'object' && attr != null && typeof attr.type === 'string' &&
['string', 'color', 'unit', 'enum', 'boolean', 'number'].includes(attr.type);
} Try / catch
try {
registerComponent(MyElement)
} catch (e) {
if (e.message.startsWith('No type found for')) {
console.error(`Fix attribute type in element definition: ${e.message}`)
} else throw e
} Prevention
- Copy type names from official mjml docs, not from memory.
- Type-check custom element definitions against the core types list.
- Re-check custom types after mjml-core upgrades.
When it happens
Trigger: Declaring an attribute type in a custom element definition (e.g. type: 'colorr' or an unsupported type like 'email') that no registered matcher accepts, which then flows into initializeType when the element's types are initialized.
Common situations: Typo in a custom component's attribute type; copying a type name from another validation library (e.g. Joi/Zod style names); core upgrade or downgrade where a type was removed or renamed; building custom elements with an unregistered custom type.
Related errors
- Mixed variable syntax detected. Use either CSS property synt
- ValidationError: \n ${errors.map((e) => e.formattedMessage).
- e.formattedMessage (compiled MJML errors printed via console
- [MJML] mj-include tags were found but includes are disabled
- [MJML security] includePath "${p}" is the root directory, wh
AI-assisted analysis of mjmlio/mjml@6c01d35af5 (2026-09-02).
Data as JSON: /api/errors/6d7c0f015093ae6d.
Report an issue: GitHub.