{"record":{"id":"233b626782b927fc","repo":"siyuan-note/siyuan","slug":"conf-language-112-formatted-with-invalidchar-loc","errorCode":null,"errorMessage":"Conf.Language(112) formatted with invalidChar (localized marker-not-allowed message)","messagePattern":"Conf\\.Language\\(112\\) formatted with invalidChar \\(localized marker-not-allowed message\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/bookmark.go","lineNumber":98,"sourceCode":"\t\t\tif err = writeTreeUpsertQueue(tree); err != nil {\n\t\t\t\tutil.ClearPushProgress(100)\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tutil.RandomSleep(50, 150)\n\t}\n\n\tindexHistoryDir(filepath.Base(historyDir), util.NewLute())\n\tsql.FlushQueue()\n\n\tutil.ReloadUI()\n\treturn\n}\n\nfunc RenameBookmark(oldBookmark, newBookmark string) (err error) {\n\tif invalidChar := treenode.ContainsMarker(newBookmark); \"\" != invalidChar {\n\t\treturn fmt.Errorf(Conf.Language(112), invalidChar)\n\t}\n\n\tnewBookmark = strings.TrimSpace(newBookmark)\n\tif \"\" == newBookmark {\n\t\treturn errors.New(Conf.Language(126))\n\t}\n\n\tif oldBookmark == newBookmark {\n\t\treturn\n\t}\n\n\tutil.PushEndlessProgress(Conf.Language(110))\n\tdefer util.ClearPushProgress(100)\n\n\tbookmarks := sql.QueryBookmarkBlocks()\n\ttreeBlocks := map[string][]string{}\n\tfor _, bm := range bookmarks {\n\t\tif blocks, ok := treeBlocks[bm.RootID]; !ok {","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/bookmark.go#L80-L116","documentation":"Renaming a bookmark to a name containing reserved Markdown/markup marker characters is rejected. treenode.ContainsMarker scans the new name for characters that would be interpreted as block markers and returns the offending character, which is interpolated into the localized message Conf.Language(112). This protects document structure from names that would corrupt rendering when used as block text.","triggerScenarios":"Calling RenameBookmark (via renameBookmark API handler or bookmarkRename menu action) with newBookmark containing characters like [ ] ( ) ** ` # or other marker characters detected by treenode.ContainsMarker.","commonSituations":"User pastes a heading or link-like string into the bookmark rename dialog; plugin/automation renames bookmarks using titles that contain markup; batch rename scripts that do not sanitize names.","solutions":["Remove marker characters from the new bookmark name before calling the API.","Strip or escape markers client-side using the same character set as treenode.ContainsMarker.","Show the localized message (Conf.Language(112)) to the user and prompt for a different name.","In automation, sanitize names with a regexp removing marker characters."],"exampleFix":"// before\nerr := model.RenameBookmark(old, \"[Important] notes\")\n// after\nsafe := strings.Map(func(r rune) rune {\n    if strings.ContainsRune(\"[](){}#*`_~\", r) { return -1 }\n    return r\n}, \"[Important] notes\")\nerr := model.RenameBookmark(old, safe)","handlingStrategy":"validation","validationCode":"function hasMarkerChars(name) { return /[](){}#*`_~]/.test(name) }","typeGuard":null,"tryCatchPattern":"err := model.RenameBookmark(old, name)\nif err != nil && strings.Contains(err.Error(), invalidCharHint) {\n    // show localized message Conf.Language(112) and re-prompt\n}","preventionTips":["Sanitize bookmark names by stripping marker characters before renaming","Show marker restrictions in rename dialogs upfront","Test automation inputs for markup characters from titles/headings"],"tags":["bookmark","validation","markers"],"backgroundTag":"invalid-identifier-format","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}