siyuan-note/siyuan · error
Invalid attribute view rich text style entity
Error message
Invalid attribute view rich text style entity
What it means
restoreAVRichTextBlockDOMStyleEntities renders attribute-view rich text kramdown by first protecting style-entity tokens (e.g. kramdown span/style entities) so the browser HTML parser cannot mangle them, then restoring them into the parsed DOM. After restoration it verifies that every protection token was actually restored into the template's DOM. If some tokens never reappear — meaning the parser dropped or altered the placeholder elements — this internal invariant is violated and the Error 'Invalid attribute view rich text style entity' is thrown from restoreAVRichTextBlockDOMStyleEntities.
Source
Thrown at app/src/protyle/render/av/richText.ts:253
if (node.nodeType === Node.TEXT_NODE) {
node.nodeValue = replaceProtections(node.nodeValue || "", false, restored);
return;
}
node.childNodes.forEach(visit);
};
visit(element);
};
template.content.querySelectorAll('[data-type="NodeCodeBlock"], span[data-type~="code"]')
.forEach(restoreLiteralText);
template.content.querySelectorAll<HTMLElement>(
'[data-type="NodeMathBlock"][data-content], [data-type="NodeMathBlock"] [data-content], ' +
'span[data-type~="inline-math"][data-content]'
).forEach((element) => {
element.setAttribute("data-content",
replaceProtections(element.getAttribute("data-content") || "", false, restored));
});
if (protections.some((protection) => !restored.has(protection.token))) {
throw new Error("Invalid attribute view rich text style entity");
}
return (template.innerHTML || "").trim();
};
const parseAVRichTextKramdown = (markdown: string, lute = getAVRichTextLute()) => {
const protectedStyle = protectAVRichTextKramdownStyleEntities(markdown);
return restoreAVRichTextBlockDOMStyleEntities(lute.Md2BlockDOM(protectedStyle.content),
protectedStyle.protections);
};
const getAVRichTextPlainContent = (blockDOM: string, lute: Lute) => {
const template = document.createElement("template");
template.innerHTML = blockDOM;
const blocks = Array.from(template.content.querySelectorAll<HTMLElement>(
'[data-type="NodeParagraph"], [data-type="NodeHeading"], [data-type="NodeCodeBlock"], ' +
'[data-type="NodeMathBlock"]'
)).map((element) => lute.BlockDOM2Content(element.outerHTML));
return projectAVRichTextPlainBlocks(blocks, lute.BlockDOM2Content(blockDOM));View on GitHub (pinned to 8641553a1f)
Solutions
- Inspect the rich-text value's kramdown and fix or remove malformed style-entity spans so placeholders survive HTML parsing
- Re-enter the affected rich-text cell content in the UI so the value is re-serialized into valid kramdown
- If triggered after a Lute or SiYuan upgrade, report it — the protection/restoration round-trip invariant broke and the offending input should be captured
- As a caller, wrap parseAVRichTextKramdown in try-catch and fall back to rendering the raw text instead of failing the whole cell
Example fix
// before: rendering crashes the whole AV cell
const html = parseAVRichTextKramdown(cellValue);
// after: fall back to escaped text on invalid style entities
let html;
try {
html = parseAVRichTextKramdown(cellValue);
} catch (e) {
html = escapeHtml(cellValue);
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-validate that style-entity kramdown is well-formed before rendering
const hasBalancedStyleEntities = /\{\{[^{}]*\}\}/.test(markdown) === markdown.includes("{{");
if (markdown.includes("{{") && !/\{\{[^{}]+\}\}/.test(markdown)) {
// malformed style entity — sanitize or reject before parseAVRichTextKramdown
} Try / catch
let html;
try {
html = parseAVRichTextKramdown(markdown);
} catch (e) {
if (e.message.includes("Invalid attribute view rich text style entity")) {
html = escapeHtml(markdown); // degraded but safe rendering
} else {
throw e;
}
} Prevention
- Never hand-edit kramdown style entities in AV rich text values; edit through the editor UI
- When generating rich-text values programmatically, round-trip them through parseAVRichTextKramdown in tests before persisting
- Keep SiYuan and Lute versions in sync; mismatched versions can break the protect/restore token round-trip
- Sanitize pasted content containing {{ }} style-entity syntax before inserting it into AV rich text fields
When it happens
Trigger: Call parseAVRichTextKramdown (e.g. while rendering an AV rich-text cell) with kramdown containing style-entity markup whose placeholder is lost during HTML parsing: the protected token's element is stripped, its data-content/protection attribute is dropped, or the markdown produces malformed HTML so the placeholder does not survive template parsing.
Common situations: Pasting kramdown text with broken or hand-edited style entities into an attribute-view rich text field; version changes in Lute or the sanitizer that alter how placeholders are parsed; programmatically injecting rich-text values with mismatched or duplicated style-entity tokens via the API or templates.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- unsupported attribute view rich text format [%s]
- invalid attribute view rich text span style IAL
- encoded style entity is not attached to an attribute view ri
- invalid encoded style entity in attribute view rich text spa
- parse tree [%s] failed
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/1494329fd2449cda.
Report an issue: GitHub.