{"record":{"id":"cb7664f5adfef6f8","repo":"siyuan-note/siyuan","slug":"tag-cannot-be-empty","errorCode":null,"errorMessage":"Tag cannot be empty","messagePattern":"Tag cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","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/afa823b6b4e4f183511e0bc0a3be93caa94c7c97/kernel/model/tag.go#L118-L154","documentation":"After RenameTag trims leading/trailing '/' and whitespace from the new label, i18n key 114 ('Tag cannot be empty') is returned when nothing remains. Marker validation has already passed at this point, so input like '/', '//' or whitespace-only lands here; the rename is refused before any blocks are touched.","triggerScenarios":"Renaming a tag to '/', '//', or a blank/whitespace string; clearing the input field in the rename dialog.","commonSituations":"A user tries to 'delete' a tag by renaming it to empty — the supported way is removing the #tag markup from blocks.","solutions":["Provide a real, non-empty label","To remove a tag, delete the #tag markup from the blocks instead of renaming to empty"],"exampleFix":"// before\nmodel.RenameTag(\"work\", \" /\")\n// after\nmodel.RenameTag(\"work\", \"work-2026\")","handlingStrategy":"validation","validationCode":"label := strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(strings.TrimSpace(newLabel), \"/\"), \"/\"))\nif label == \"\" {\n\treturn errors.New(\"tag label is empty after trimming\")\n}\nmodel.RenameTag(oldLabel, label)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Disable the rename confirm button while the trimmed label is empty","Route 'delete tag' intents to removing the #tag markup, not renaming"],"tags":["tag","rename","empty-value","validation"],"backgroundTag":"empty-tag-name","analyzedSha":"afa823b6b4e4f183511e0bc0a3be93caa94c7c97","analyzedAt":"2026-08-18T17:04:10.865Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}