{"record":{"id":"6b91afaece31ee03","repo":"mjmlio/mjml","slug":"unbalanced-template-delimiters-found-in-css-det","errorCode":null,"errorMessage":"Unbalanced template delimiters found in CSS: ${details}. ${getTemplateDelimiterRecoveryMessage(contextName)}","messagePattern":"Unbalanced template delimiters found in CSS: (.+?)\\. (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/mjml-core/src/index.js","lineNumber":401,"sourceCode":"    content: html,\n    didSanitize: false,\n    variableMap: {},\n    propMap: {},\n    isBlockVariable: false,\n  }\n\n  if (!shouldSanitize) {\n    return result\n  }\n\n  const broken = detectBrokenTemplateDelimitersInCss(html, syntaxes)\n  if (broken.length) {\n    const details = broken\n      .map(\n        (b) => `${b.prefix}…${b.suffix} (${b.prefixCount} open, ${b.suffixCount} close)`,\n      )\n      .join(', ')\n    throw new Error(\n      `Unbalanced template delimiters found in CSS: ${details}. ${getTemplateDelimiterRecoveryMessage(contextName)}`,\n    )\n  }\n\n  const detected = detectVariableTypeInHtml(html, syntaxes)\n  result.isBlockVariable = detected.isBlockVariable\n\n  if (!allowMixedSyntax && result.isBlockVariable && (detected.isValueVariable || detected.isPropertyVariable)) {\n    throw new Error(\n      '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.',\n    )\n  }\n\n  if (detected.isValueVariable) {\n    const sanitized = sanitizeCssValueVariablesHtml(html, syntaxes)\n    result.content = sanitized.result\n    result.variableMap = sanitized.variableMap\n    result.didSanitize = true","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/mjmlio/mjml/blob/6c01d35af5da14108b86bbf052232e99de7ca755/packages/mjml-core/src/index.js#L383-L419","documentation":"sanitizeTemplateVariablesInHtml scans CSS for template delimiters (e.g. {{ }}) before mjml-core processes template variables. If it finds delimiters whose opening and closing counts are unbalanced (e.g. '{{x}' or '{{x}}}') it throws with the specific broken delimiters and counts, plus a recovery message naming the context. The library refuses to guess how to sanitize CSS with malformed interpolation syntax.","triggerScenarios":"Calling sanitizeTemplateVariablesInHtml (directly or via sanitizationResult) with HTML/CSS containing an odd number of '{{' or '}}' occurrences, such as '{{color}}}' or a single '{' prefix like '{variable}' inside a CSS block.","commonSituations":"Hand-written email templates with typos in handlebars/Mustache placeholders; CSS inlined into <mj-style> containing literal braces that were meant to be escaped; template engines generating partial interpolation after a failed substitution.","solutions":["Read the details in the message: fix each reported prefix/suffix so open and close delimiter counts match (e.g. '{{x}' -> '{{x}}').","Escape literal braces that are not template variables, or remove stray single braces from the CSS.","Check any upstream template engine output for truncated substitutions before passing it to mjml2html.","If pre/post delimiters are misconfigured, align the syntaxes option with the delimiters actually used in the CSS."],"exampleFix":"/* before */\ncolor: {{primaryColor};\n/* after */\ncolor: {{primaryColor}};","handlingStrategy":"validation","validationCode":"function assertBalancedDelimiters(css, open = '{{', close = '}}') {\n  const o = css.split(open).length - 1;\n  const c = css.split(close).length - 1;\n  if (o !== c) throw new Error(`Unbalanced ${open}${close}: ${o} open vs ${c} close`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  const result = sanitizeTemplateVariablesInHtml(html, opts)\n} catch (e) {\n  if (e.message.startsWith('Unbalanced template delimiters')) {\n    // surface the broken delimiters to the template author\n    console.error(e.message)\n  } else throw e\n}","preventionTips":["Lint templates for stray single braces before builds.","Escape literal braces that are not template variables.","Test template rendering in CI to catch delimiter typos early."],"tags":["css","template","syntax","delimiters"],"backgroundTag":"unbalanced-template-delimiters","analyzedSha":"6c01d35af5da14108b86bbf052232e99de7ca755","analyzedAt":"2026-09-02T21:31:03.649Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}