siyuan-note/siyuan · error
Conf.Language(25) + " [" + node.ID + "]" (localized invalid
Error message
Conf.Language(25) + " [" + node.ID + "]" (localized invalid attribute name message plus block ID)
What it means
setNodeAttrs0 validates every attribute name (lower-cased) with isValidAttrName; if the name contains characters not allowed in a kramdown IAL key, the localized invalid-attribute-name message (key 25) plus the block id in brackets is returned. The whole attribute update is rejected — no partial writes.
Source
Thrown at kernel/model/blockial.go:390
}
}
}
oldAttrs = parse.IAL2Map(node.KramdownIAL)
newAttrsUnEsc := parse.IAL2MapUnEsc(node.KramdownIAL)
for name := range nameValues {
if "fold" == strings.ToLower(name) {
delete(newAttrsUnEsc, "heading-fold")
break
}
}
for name, value := range nameValues {
value = util.RemoveInvalidRetainCtrl(value)
value = strings.TrimSpace(value)
lowerName := strings.ToLower(name)
// 转换为小写再验证属性名
if !isValidAttrName(lowerName) {
err = errors.New(Conf.Language(25) + " [" + node.ID + "]")
return
}
if lowerName == "data-task" {
err = errors.New(`setting or removing [data-task] attribute is not allowed via this interface. Please use "/api/block/updateTaskListItemMarker" or "/api/block/batchUpdateTaskListItemMarker" to update the task list item marker`)
return
}
if DocSortModeAttr == lowerName {
if ast.NodeDocument != node.Type || IsBoxDoc(boxID, node.ID) {
err = fmt.Errorf("attribute [%s] is only supported on regular document roots", DocSortModeAttr)
return
}
if "" != value {
sortMode, parseErr := strconv.Atoi(value)
if nil != parseErr || !IsValidDocSortMode(sortMode) {
err = fmt.Errorf("invalid document sort mode [%s]", value)
return
}
value = strconv.Itoa(sortMode)View on GitHub (pinned to 8641553a1f)
Solutions
- Sanitize the attribute name: lowercase letters, digits, and hyphens only (custom- prefix recommended)
- Rename the offending key before calling the API
- Check the block id in the error message to locate which entry in a batch is bad
Example fix
// before
setNodeAttrs(boxID, id, map[string]string{"my key!": "v"}) // Language(25) + [id]
// after
setNodeAttrs(boxID, id, map[string]string{"custom-my-key": "v"}) Defensive patterns
Strategy: validation
Validate before calling
// TS: validate attribute names before sending
const validName = /^[a-zA-Z][a-zA-Z0-9-]*$/;
for (const k of Object.keys(attrs)) {
if (!validName.test(k)) throw new Error(`invalid attr name: ${k}`);
} Type guard
function hasValidAttrNames(attrs: Record<string,string>): boolean {
return Object.keys(attrs).every(k => /^[a-zA-Z][a-zA-Z0-9-]*$/.test(k));
} Prevention
- Lowercase and sanitize attribute names derived from user input
- Restrict plugin attribute writes to custom-* keys
- Avoid spaces and punctuation in attribute names
When it happens
Trigger: Calling setNodeAttrs / BatchSetBlockAttrs / setNodeAttrsWithTx with an attribute key containing invalid characters (spaces, uppercase handling aside, symbols like : " = or other IAL-breaking characters).
Common situations: Plugins building attribute names dynamically from user input; scripts using keys with spaces or punctuation; copying HTML attribute names that contain invalid characters.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- The attribute name can only contain lowercase English letter
- data?.msg || data?.message || window.siyuan.languages._kerne
- wrong layout type
- filter nesting depth exceeds the maximum allowed
- Do not include symbols \ / : * ? " ' < > |
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/d334afd489e44bf6.
Report an issue: GitHub.