{"record":{"id":"006e40bf4b80e828","repo":"siyuan-note/siyuan","slug":"conf-language-114","errorCode":null,"errorMessage":"Conf.Language(114)","messagePattern":"Conf\\.Language\\(114\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"kernel/model/tag.go","lineNumber":136,"sourceCode":"\n\tupdateAttributeViewBlockText(updateNodes)\n\n\tsql.FlushQueue()\n\tutil.PushClearProgress()\n\treturn\n}\n\nfunc RenameTag(oldLabel, newLabel string) (err error) {\n\tif invalidChar := treenode.ContainsMarker(newLabel); \"\" != invalidChar {\n\t\treturn fmt.Errorf(Conf.Language(112), invalidChar)\n\t}\n\n\tnewLabel = strings.TrimPrefix(newLabel, \"/\")\n\tnewLabel = strings.TrimSuffix(newLabel, \"/\")\n\tnewLabel = strings.TrimSpace(newLabel)\n\n\tif \"\" == newLabel {\n\t\treturn errors.New(Conf.Language(114))\n\t}\n\n\tif oldLabel == newLabel {\n\t\treturn\n\t}\n\n\tutil.PushEndlessProgress(Conf.Language(110))\n\tutil.RandomSleep(500, 1000)\n\n\ttags := sql.QueryTagSpansByLabel(oldLabel)\n\ttreeBlocks := map[string][]string{}\n\tfor _, tag := range tags {\n\t\tif blocks, ok := treeBlocks[tag.RootID]; !ok {\n\t\t\ttreeBlocks[tag.RootID] = []string{tag.BlockID}\n\t\t} else {\n\t\t\ttreeBlocks[tag.RootID] = append(blocks, tag.BlockID)\n\t\t}\n\t}","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/tag.go#L118-L154","documentation":"RenameTag refuses to rename a tag to an empty label. After stripping leading/trailing slashes and whitespace from newLabel, if nothing remains the kernel returns the localized message Conf.Language(114) = \"Tag cannot be empty\". Tags in SiYuan are hierarchical (\"/parent/child/\"), so the slash trimming is normal normalization; only a fully-empty result is rejected.","triggerScenarios":"Calling /api/tag/renameTag (model.RenameTag) with newLabel that is empty, only whitespace, only slashes (\"/\", \"///\"), or a mix like \" / \" — all normalize to \"\".","commonSituations":"A plugin or UI script clears the rename input before submitting; batch rename scripts iterating a tag list where one entry is blank; trimming logic upstream already removed the text the user typed.","solutions":["Pass a non-empty newLabel containing at least one non-slash, non-whitespace character","Check the normalized label client-side (trim spaces and '/') before calling renameTag and show a validation message instead","If migrating from an old tag value that was itself empty, remove the tag with RemoveTag instead of renaming it to \"\""],"exampleFix":"// before\nrenameTag(oldLabel, \"\") // error: Tag cannot be empty\n// after\nconst newLabel = input.trim()\nif (newLabel) { await fetchPost(\"/api/tag/renameTag\", {oldLabel, newLabel}) }","handlingStrategy":"validation","validationCode":"const normalized = newLabel.replace(/^\\/+|\\/+$/g, \"\").trim();\nif (!normalized) throw new Error(\"Tag cannot be empty\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always trim and strip slashes from the proposed tag name before submitting","Reject empty/whitespace-only inputs in the UI before the API call","Check treenode.ContainsMarker-equivalent characters first (error 112) to avoid chained validation failures"],"tags":["validation","empty-string","tags"],"backgroundTag":"empty-required-field","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}