mjmlio/mjml · error · Error

Mixed variable syntax detected. Use either CSS property synt

Error message

Mixed variable syntax detected. Use either CSS property syntax (e.g., color: {{variable}}) OR block syntax (e.g., {{variable}}), not both in the same document.

What it means

sanitizeTemplateVariablesInHtml detects which template-variable style a document uses: CSS value/property syntax (color: {{var}}) or block syntax ({{var}} on its own). When both styles appear in the same document and allowMixedSyntax is not enabled, the library throws because the two styles require different sanitization passes that cannot be combined safely.

Source

Thrown at packages/mjml-core/src/index.js:410

  }

  const broken = detectBrokenTemplateDelimitersInCss(html, syntaxes)
  if (broken.length) {
    const details = broken
      .map(
        (b) => `${b.prefix}…${b.suffix} (${b.prefixCount} open, ${b.suffixCount} close)`,
      )
      .join(', ')
    throw new Error(
      `Unbalanced template delimiters found in CSS: ${details}. ${getTemplateDelimiterRecoveryMessage(contextName)}`,
    )
  }

  const detected = detectVariableTypeInHtml(html, syntaxes)
  result.isBlockVariable = detected.isBlockVariable

  if (!allowMixedSyntax && result.isBlockVariable && (detected.isValueVariable || detected.isPropertyVariable)) {
    throw new Error(
      'Mixed variable syntax detected. Use either CSS property syntax (e.g., color: {{variable}}) OR block syntax (e.g., {{variable}}), not both in the same document.',
    )
  }

  if (detected.isValueVariable) {
    const sanitized = sanitizeCssValueVariablesHtml(html, syntaxes)
    result.content = sanitized.result
    result.variableMap = sanitized.variableMap
    result.didSanitize = true
  }

  if (detected.isPropertyVariable) {
    const sanitizedProp = sanitizeCssPropertyVariablesHtml(result.content, syntaxes)
    result.content = sanitizedProp.result
    result.propMap = sanitizedProp.propMap
    result.didSanitize = true
  }

View on GitHub (pinned to 6c01d35af5)

Solutions

  1. Rewrite the document to use a single variable style: convert inline 'color: {{var}}' usages to block syntax or vice versa.
  2. Pass allowMixedSyntax: true if mixed styles are intentional and safe for your pipeline.
  3. Split the document into separate MJML files, each using one style.
  4. Search the HTML for '{{' occurrences and normalize all placeholders with a codemod/lint rule.

Example fix

/* before: mixed */
{{bgColor}}
padding: {{padding}};
/* after: one style (block) */
{{bgColor}}
{{padding}}
/* or: pass { allowMixedSyntax: true } */
Defensive patterns

Strategy: validation

Validate before calling

function detectMixedSyntax(html) {
  const block = /(^|\n)\s*\{\{\s*\w+\s*\}\}\s*(\n|$)/.test(html);
  const value = /:\s*[^;{]*\{\{\s*\w+\s*\}\}/.test(html);
  return block && value;
}
if (detectMixedSyntax(html)) throw new Error('Mixed template syntax in document');

Try / catch

try {
  return sanitizeTemplateVariablesInHtml(html, opts)
} catch (e) {
  if (e.message.startsWith('Mixed variable syntax')) {
    console.error('Normalize placeholders to a single style:', e.message)
  } else throw e
}

Prevention

When it happens

Trigger: Calling sanitizeTemplateVariablesInHtml (via sanitizationResult) on HTML where block-level '{{var}}' placeholders coexist with 'property: {{var}}' CSS usages while allowMixedSyntax is false/omitted.

Common situations: Merging email sections authored by different people or tools, one using block placeholders and the other inline CSS placeholders; copy-pasting snippets from two template styles into one MJML document.

Related errors


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