{"record":{"id":"b393cf7d443e642d","repo":"siyuan-note/siyuan","slug":"maximum-length-is-limited-to-512-characters","errorCode":null,"errorMessage":"Maximum length is limited to 512 characters","messagePattern":"Maximum length is limited to 512 characters","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/file.go","lineNumber":2219,"sourceCode":"\nfunc renameDoc0(boxID, p, title string) (err error) {\n\tbox := Conf.Box(boxID)\n\tif nil == box {\n\t\terr = errors.New(Conf.Language(0))\n\t\treturn\n\t}\n\n\tFlushTxQueue()\n\tluteEngine := util.NewLute()\n\ttree, err := filesys.LoadTree(box.ID, p, luteEngine)\n\tif err != nil {\n\t\treturn\n\t}\n\n\ttitle = normalizeDocTitle(title)\n\tif 512 < utf8.RuneCountInString(title) {\n\t\t// 限制笔记本名和文档名最大长度为 `512` https://github.com/siyuan-note/siyuan/issues/6299\n\t\treturn errors.New(Conf.Language(106))\n\t}\n\n\tvar isEmpty bool\n\tif \"\" == title {\n\t\ttitle = Conf.language(16)\n\t\tisEmpty = true\n\t}\n\t// 先规范化输入得到实际会存储的标题，再与旧标题比较\n\ttitleChanged := tree.Root.IALAttr(\"title\") != title\n\n\tvar emptyAttrUpdated bool\n\tif titleChanged {\n\t\ttree.HPath = path.Join(path.Dir(tree.HPath), title)\n\t\ttree.Root.SetIALAttr(\"title\", title)\n\t}\n\n\t// 按需同步“无标题”标记（仅更新 IAL，不触发子树重命名等）\n\tisTitleEmpty := tree.Root.IALAttr(NodeAttrTitleEmpty) == \"true\"","sourceCodeStart":2201,"sourceCodeEnd":2237,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/afa823b6b4e4f183511e0bc0a3be93caa94c7c97/kernel/model/file.go#L2201-L2237","documentation":"renameDoc0 (kernel/model/file.go:2219) enforces the 512-rune cap on document titles (issue #6299). The input first passes normalizeDocTitle (strips '/', removes invalid characters, trims), then utf8.RuneCountInString(title) must be <= 512 or the call fails with Conf.Language(106). Counting is per Unicode rune, not per byte — a CJK title fails at 513 characters while a byte-count check would have allowed far fewer, and ZWJ emoji sequences count as multiple runes.","triggerScenarios":"POST /api/filetree/renameDoc / renameDocByID with a title longer than 512 runes after normalization; typically programmatic titles (auto-generated summaries, concatenated lists, pasted blobs) rather than hand-typed names.","commonSituations":"Plugins that derive titles from document content; imports where the first line becomes the title; automated pipelines naming docs from long strings.","solutions":["Truncate the title to 512 runes (count runes, not bytes/UTF-16 units) before calling the API","Validate in UI input fields with a rune counter so users see the limit before submitting","For generated titles, cap the source text earlier (e.g. first 500 runes + ellipsis) to leave room for normalization differences"],"exampleFix":"// before\nfetchPost('/api/filetree/renameDoc', {notebook, path, title: autoSummary}) // may exceed 512 runes\n\n// after\nconst title = Array.from(autoSummary).slice(0, 512).join('') // rune-safe truncation\nfetchPost('/api/filetree/renameDoc', {notebook, path, title})","handlingStrategy":"validation","validationCode":"// Rune-accurate title clamp before renameDoc\nfunc clampTitle(title string) string {\n\tr := []rune(normalizeDocTitle(title))\n\tif 512 < len(r) {\n\t\treturn string(r[:512])\n\t}\n\treturn string(r)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Count runes, not bytes or UTF-16 code units — CJK and ZWJ emoji sequences shift the count","Normalize (strip '/' and invalid chars) before measuring, because the kernel measures after normalization","Cap auto-generated titles at generation time (first N runes of source text)"],"tags":["siyuan","rename-doc","validation","limits","unicode"],"backgroundTag":"max-length-exceeded","analyzedSha":"afa823b6b4e4f183511e0bc0a3be93caa94c7c97","analyzedAt":"2026-08-18T17:04:10.865Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}