siyuan-note/siyuan · error
inconsistent attribute view rich text style entity sentinel
Error message
inconsistent attribute view rich text style entity sentinel
What it means
During restoration of protected style entities in an attribute view rich text tree, every protection entry must carry the same sentinel marker that was generated when the entities were protected. restoreValueTextRichTreeStyleEntities derives the expected sentinel from protections[0] and rejects the batch if any later entry carries a different sentinel. This is an internal invariant: protections are always created together by protectValueTextRichStyleEntities, so a mismatch means the slice was assembled or mutated incorrectly.
Source
Thrown at kernel/av/value.go:1921
}
return builder.String(), protections
}
func restoreValueTextRichTreeStyleEntities(tree *parse.Tree,
protections []valueTextRichStyleEntityProtection) (err error) {
if 1 > len(protections) {
return
}
sentinel := protections[0].sentinel
stylePairs := make([]string, 0, len(protections)*2)
literalPairs := make([]string, 0, len(protections)*2)
textMarkCodePairs := make([]string, 0, len(protections)*2)
textMarkInlineMathPairs := make([]string, 0, len(protections)*2)
tokenIndexes := make(map[string]int, len(protections))
restored := make([]bool, len(protections))
for i, protection := range protections {
if sentinel != protection.sentinel {
return fmt.Errorf("inconsistent attribute view rich text style entity sentinel")
}
tokenIndexes[protection.token] = i
stylePairs = append(stylePairs, protection.token, protection.decoded)
literalPairs = append(literalPairs, protection.token, protection.encoded)
encoded := strings.ReplaceAll(protection.encoded, "&", "&")
textMarkCodePairs = append(textMarkCodePairs, protection.token, encoded)
textMarkInlineMathPairs = append(textMarkInlineMathPairs, protection.token,
strings.ReplaceAll(encoded, "&", "&"))
}
styleReplacer := strings.NewReplacer(stylePairs...)
literalReplacer := strings.NewReplacer(literalPairs...)
textMarkCodeReplacer := strings.NewReplacer(textMarkCodePairs...)
textMarkInlineMathReplacer := strings.NewReplacer(textMarkInlineMathPairs...)
ast.Walk(tree.Root, func(node *ast.Node, entering bool) ast.WalkStatus {
if !entering {
return ast.WalkContinue
}View on GitHub (pinned to 8641553a1f)
Solutions
- Ensure all protections passed to restoreValueTextRichTreeStyleEntities come from a single protectValueTextRichStyleEntities run over the same content
- Verify the sentinel field of every protection entry matches protections[0].sentinel before calling the restore function
- If merging content, re-run protection and restoration as one unified pass instead of stitching slices
Example fix
// before protections = append(oldProtections, newProtections...) restoreValueTextRichTreeStyleEntities(tree, protections) // after allProtected, _ := protectValueTextRichStyleEntities(combinedStyle, sentinel, offset) restoreValueTextRichTreeStyleEntities(tree, allProtected)
Defensive patterns
Strategy: validation
Validate before calling
const sentinel0 = protections[0]?.sentinel
if (!protections.every(p => p.sentinel === sentinel0)) {
throw new Error("mixed sentinel protection sets; re-run protection in a single pass")
} Prevention
- Always generate and restore protections within one function scope
- Never concatenate protection slices from different protect passes
When it happens
Trigger: Calling restoreValueTextRichTreeStyleEntities (via the rich text normalization path, e.g. NormalizeValueTextRich on a ValueText with a rich payload) with a protections slice whose entries were produced by different protectValueTextRichStyleEntities invocations, or with a programmatically modified slice where one entry's sentinel field differs from the first entry's.
Common situations: Kernel-side code combining protection slices from two separate protect passes; tests or tooling that hand-construct valueTextRichStyleEntityProtection entries with mismatched sentinel strings; a partial refactor that re-protects part of a document under a new sentinel but restores with the old slice.
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
- ErrRichTextSpecMismatch
- unsupported attribute view rich text spec [%d]
- unsupported attribute view rich text format [%s]
- parse attribute view rich text failed
- attribute view rich text tree is missing
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/fc2e994e84ff2808.
Report an issue: GitHub.