siyuan-note/siyuan · error
The attribute name can only contain lowercase English letter
Error message
The attribute name can only contain lowercase English letters, digits, and hyphens, and must start with a lowercase English letter
What it means
In setNodeAttrs0, for each requested attribute the name is lower-cased and passed to isValidAttrName; if it fails the function returns errors.New(Conf.Language(25) + ' [' + node.ID + ']') — 'The attribute name can only contain lowercase English letters, digits, and hyphens, and must start with a lowercase English letter'. isValidAttrName (blockial.go:418) requires: non-empty, first char a-z, subsequent chars a-z/0-9/-, with the special 'custom-' prefix case also requiring a lowercase letter after the hyphen.
Source
Thrown at kernel/model/blockial.go:360
}
}
}
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
}
// 处理文档标签 https://github.com/siyuan-note/siyuan/issues/13311
if lowerName == "tags" {
var tags []string
tmp := strings.SplitSeq(value, ",")
for t := range tmp {
t = strings.TrimSpace(t)
if "" != t {
tags = append(tags, t)
}
}
tags = gulu.Str.RemoveDuplicatedElem(tags)View on GitHub (pinned to 251596fc0d)
Solutions
- Lower-case and sanitize the key client-side before sending: match ^[a-z][a-z0-9-]*(custom-[a-z][a-z0-9-]*)?$ semantics.
- Replace disallowed characters (spaces/underscores) with hyphens and strip the rest.
- For user-defined keys, prefer the 'custom-' prefix convention.
Example fix
// before
attrs := map[string]string{"Created_At": "2024-01-01"}
// after: normalize the name to the allowed alphabet
name := strings.ToLower("Created_At")
name = strings.ReplaceAll(name, "_", "-")
attrs := map[string]string{name: "2024-01-01"} Defensive patterns
Strategy: validation
Validate before calling
// Replicate isValidAttrName before sending.
func validAttrName(name string) bool {
name = strings.ToLower(name)
if name == "" || name[0] < 'a' || name[0] > 'z' { return false }
for i := 0; i < len(name); i++ {
c := name[i]
if !((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-') { return false }
}
return true
} Try / catch
// HTTP caller: normalize then retry on this specific error.
if (r.code === -1 && /attribute name/i.test(r.msg)) {
const norm = key.toLowerCase().replace(/[^a-z0-9-]/g, '-')
attrs[norm] = attrs[key]; delete attrs[key]
r = await fetchSyncPost('/api/attr/setBlockAttrs', {id, attrs})
} Prevention
- Sanitize external field names (lowercase, hyphenate) before using them as IAL keys.
- Prefer the 'custom-' prefix convention for user-defined keys.
- Reject 'custom-' with no suffix, uppercase, underscores, and whitespace client-side.
When it happens
Trigger: POST /api/attr/setBlockAttrs (or batchSetBlockAttrs) with an attr key like 'Foo', '1abc', 'name space', 'custom-A', 'custom-' (prefix only), or any key containing underscore/uppercase/non-ASCII. Also via MCP attr tool and the CLI attr command.
Common situations: Plugins externalizing an internal field name verbatim (CamelCase or with underscores); user-facing 'key' input that wasn't normalized; migration tooling that copied arbitrary metadata keys.
Related errors
- Encrypted notebooks do not support this operation
- setting or removing [data-task] attribute is not allowed via
- Failed to update agent session permission
- Agent capability name and description are required
- invalid frontend capability ID: %s
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/3a8ae83d150cf7d8.
Report an issue: GitHub.