nexu-io/open-design · error · Error
raw template interpolation is not supported
Error message
raw template interpolation is not supported
What it means
Thrown by renderHtmlTemplateV1() when the template contains a raw-interpolation construct — either triple-mustache `{{{ ... }}}` or ampersand-mustache `{{& ... }}`. These are Mustache/Handlebars conventions for inserting unescaped HTML, which the live artifact renderer rejects outright as an XSS control: all scalar substitution in html_template_v1 is auto-escaped via escapeHtmlTemplateValue(), and there is no opt-out.
Source
Thrown at apps/daemon/src/live-artifacts/render.ts:269
const itemTemplate = element.replace(REPEAT_DIRECTIVE, '');
if (findRepeatDirective(itemTemplate)) {
throw new Error('nested data-od-repeat is not supported');
}
out += interpolateScalars(html.slice(cursor, openTagStart), resolve);
for (const item of readArray(arrayPath)) {
out += renderFragment(itemTemplate, childResolver(resolve, varName, item), readArray);
}
cursor = elementEnd;
}
return out;
}
export function renderHtmlTemplateV1(input: LiveArtifactRenderInput): LiveArtifactRenderOutput {
validateHtmlTemplateV1Security(input.templateHtml);
if (RAW_TEMPLATE_INTERPOLATION.test(input.templateHtml)) {
throw new Error('raw template interpolation is not supported');
}
const resolve = rootResolver(input.dataJson);
const readArray: ArrayReader = (arrayPath) => {
const value = readTemplatePath(input.dataJson, arrayPath);
if (!Array.isArray(value)) throw new Error(`data-od-repeat source is not an array: ${arrayPath}`);
return value;
};
return { html: renderFragment(input.templateHtml, resolve, readArray) };
}
View on GitHub (pinned to 5be4028344)
Solutions
- Replace raw insertion with the standard escaped form `{{data.htmlBlob}}` — the value is HTML-escaped automatically, which is the intended behavior.
- If you genuinely need rich HTML, pre-render it into the artifact's static preview HTML outside the template pipeline rather than injecting through a binding.
- Remove any stray `{{{`/`}}}` or `{{&`/`}}` tokens from the template (e.g. documentation strings that literally show the syntax).
Example fix
// before
<div>{{{data.description}}}</div>
// after
<div>{{data.description}}</div> Defensive patterns
Strategy: validation
Validate before calling
const RAW_TEMPLATE_INTERPOLATION = /{{{[^{}]*}}}|{{\s*&[^{}]*}}/;
function assertNoRawInterpolation(templateHtml: string): void {
if (RAW_TEMPLATE_INTERPOLATION.test(templateHtml)) {
throw new Error('template uses raw interpolation ({{{...}}} or {{& ...}}) — convert to escaped {{...}}');
}
}
assertNoRawInterpolation(input.templateHtml); Prevention
- Always use double-brace `{{...}}` for auto-escaped substitution.
- When porting a Mustache/Handlebars template, search-and-replace `{{{` → `{{` and `{{&` → `{{`.
- Never insert untrusted HTML via a binding; if rich HTML is required, render it statically outside the template pipeline.
When it happens
Trigger: Template.html contains `{{{data.htmlBlob}}}` or `{{& data.htmlBlob}}` intending to inject raw HTML. Also triggered by an LLM that has seen Handlebars examples and reproduces the raw-insertion syntax.
Common situations: Migrating an existing Mustache/Handlebars template into a live artifact; agent trained on templating docs emits triple-brace; developer assumes raw HTML insertion is needed for rich text and reaches for the familiar `{{{ }}}`.
Related errors
- script elements are not supported in live artifact previews
- iframe elements are not supported in live artifact previews
- srcdoc attributes are not supported in live artifact preview
- event handler attributes are not supported in live artifact
- javascript: URLs are not supported in live artifact previews
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/c5fc9d37aa1b4dae.
Report an issue: GitHub.