{"record":{"id":"30493412f29f2727","repo":"siyuan-note/siyuan","slug":"conf-language-112-invalidchar","errorCode":null,"errorMessage":"Conf.Language(112), invalidChar","messagePattern":"Conf\\.Language\\(112\\), invalidChar","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/tag.go","lineNumber":128,"sourceCode":"\n\tindexHistoryDir(filepath.Base(historyDir), util.NewLute())\n\tsql.FlushQueue()\n\n\treloadTreeIDs = gulu.Str.RemoveDuplicatedElem(reloadTreeIDs)\n\tfor _, id := range reloadTreeIDs {\n\t\tReloadProtyle(id)\n\t}\n\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)","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/tag.go#L110-L146","documentation":"RenameTag validates the new tag label with treenode.ContainsMarker before performing the rename. ContainsMarker (kernel/treenode/marker.go:24) rejects ASCII strings containing marker characters (characters that have special meaning in Markdown/attribute syntax), and RenameTag returns fmt.Errorf(Conf.Language(112), invalidChar) — a localized message with the offending character interpolated. The error means the requested new tag label contains a reserved marker character and cannot be used.","triggerScenarios":"Calling RenameTag (API /api/format/tagRenameContract, or the tag panel rename dialog) with newLabel containing an ASCII marker character such as #, /, [, ], (, ), or other IsMarker characters. Non-ASCII input bypasses the check (ContainsMarker returns \"\" for non-ASCII strings), so this fires specifically for ASCII labels with marker chars. Note the check runs on the raw newLabel, before trimming surrounding '/' and whitespace.","commonSituations":"User pastes a Markdown heading like '#todo' or a hierarchical path '/work/project/' intending slash hierarchy; scripts generating tags from file names or issue titles containing brackets or parentheses; batch-rename automation that doesn't sanitize labels.","solutions":["Remove the marker character (e.g. '#', '/', '[]') from the new label and retry the rename.","Strip leading/trailing '/' and whitespace yourself before calling, since the marker check runs before trimming.","Sanitize programmatically: filter out ASCII marker characters from the label before invoking RenameTag.","Use the localized message text (Language(112)) which names the offending character to guide the user."],"exampleFix":"// before: raw user input passed straight to the API\nawait fetchPost(\"/api/format/renameTag\", {oldLabel: oldTag, newLabel: input});\n\n// after: reject marker characters up front\nconst markerChars = /[\\x20-\\x7e]/; // combined with the kernel's marker set\nif (/[#\\/[\\]()!`*~_>-]/.test(input)) {\n    showMessage(\"The new tag name contains an invalid character (e.g. # or /)\");\n} else {\n    await fetchPost(\"/api/format/renameTag\", {oldLabel: oldTag, newLabel: input.trim().replace(/^\\/|\\/$/g, \"\")});\n}","handlingStrategy":"validation","validationCode":"// reject marker characters in the new tag label before calling the API\nfunction isValidTagLabel(label) {\n  if (!/^\\x00-\\x7f*$/.test(label)) return true; // non-ASCII bypasses kernel check\n  return !/[#\\/[\\]()!`*~_{}>'\"~@+$%^&|=;:,?<\\\\ -]/.test(label.replace(/^\\/|\\/$/g, \"\").trim());\n}\nif (!isValidTagLabel(newLabel)) throw new Error(\"tag name contains an invalid marker character\");","typeGuard":"function hasMarkerChar(label) {\n  if (!label || !/^[-\\x7f]*$/.test(label)) return false; // non-ASCII is allowed by the kernel\n  const markers = \"#/[]()!`*~_-{}>\\\"'\"; // mirror treenode.IsMarker set\n  return [...label].some(c => markers.includes(c));\n}","tryCatchPattern":"try {\n  await fetchPost(\"/api/format/renameTag\", {oldLabel, newLabel});\n} catch (e) {\n  showMessage(e.message); // localized: names the offending character\n}","preventionTips":["Sanitize tag labels (strip leading/trailing '/' and whitespace) before renaming","Do not generate tags from raw Markdown/heading text containing #, brackets, or slashes","Validate input in the tag-rename dialog before submitting","In batch renames, pre-filter labels with the kernel's marker-character rules"],"tags":["go","validation","tags","input-sanitization"],"backgroundTag":"invalid-argument-value","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"}