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

  1. Inspect the rich-text value's kramdown and fix or remove malformed style-entity spans so placeholders survive HTML parsing
  2. Re-enter the affected rich-text cell content in the UI so the value is re-serialized into valid kramdown
  3. If triggered after a Lute or SiYuan upgrade, report it — the protection/restoration round-trip invariant broke and the offending input should be captured
  4. 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

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


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/1494329fd2449cda. Report an issue: GitHub.