{"record":{"id":"1f94c7e08043e391","repo":"siyuan-note/siyuan","slug":"bookmark-cannot-be-empty","errorCode":null,"errorMessage":"Bookmark cannot be empty","messagePattern":"Bookmark cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/bookmark.go","lineNumber":103,"sourceCode":"\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 {\n\t\t\ttreeBlocks[bm.RootID] = []string{bm.ID}\n\t\t} else {\n\t\t\ttreeBlocks[bm.RootID] = append(blocks, bm.ID)\n\t\t}\n\t}","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/afa823b6b4e4f183511e0bc0a3be93caa94c7c97/kernel/model/bookmark.go#L85-L121","documentation":"model.RenameBookmark rejects a new bookmark name that is empty after strings.TrimSpace. This is the second validation, after the marker check, and uses localized message 126 ('Bookmark cannot be empty'). An empty string is the API-supported way to signal invalid input, not a delete — bookmarks are removed by unsetting them on blocks, not renamed to nothing.","triggerScenarios":"POST /api/bookmark/renameBookmark with newBookmark '', '   ', or a string that is only whitespace; also a name that was entirely marker characters is caught earlier, not here.","commonSituations":"Forms that submit before the user types a name, or scripts that pass an undefined/null coerced to '' when the desired name field is missing.","solutions":["Require a non-empty trimmed name in the UI before calling the API","To remove a bookmark from blocks, set/unset the 'bookmark' attribute via setBlockAttrs instead of renaming to empty","Guard scripts: skip the call when !newBookmark.trim()"],"exampleFix":"// before\nrenameBookmark(oldName, ''); // error\n\n// after\nif (newName.trim()) { renameBookmark(oldName, newName.trim()); }","handlingStrategy":"validation","validationCode":"const name = String(newBookmark ?? '').trim();\nif (!name) throw new Error('bookmark name required');","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Disable submit until the name is non-empty after trim","To remove a bookmark, unset the block's 'bookmark' attribute instead of renaming"],"tags":["bookmark","validation","api"],"backgroundTag":"empty-input","analyzedSha":"afa823b6b4e4f183511e0bc0a3be93caa94c7c97","analyzedAt":"2026-08-18T17:04:10.865Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}