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

  1. Check the message's typeConfig value and fix the typo / use a supported type (string, color, unit, enum, etc.).
  2. If you need a custom type, register a matching type constructor in the types registry before initializing elements.
  3. Grep your component definitions for the offending type string and correct all occurrences.
  4. 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

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


AI-assisted analysis of mjmlio/mjml@6c01d35af5 (2026-09-02). Data as JSON: /api/errors/6d7c0f015093ae6d. Report an issue: GitHub.