{"record":{"id":"2572d358b21d368c","repo":"siyuan-note/siyuan","slug":"conf-language-151-assets","errorCode":null,"errorMessage":"Conf.Language(151)","messagePattern":"Conf\\.Language\\(151\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/assets.go","lineNumber":1669,"sourceCode":"\t// 加密笔记本的资源磁盘文件名参与 AAD，重命名需要重新封装密文，当前不支持。\n\tif absPath, absErr := GetAssetAbsPathInBox(oldPath, \"\"); absErr == nil {\n\t\tif IsEncryptedAssetPath(absPath) {\n\t\t\terr = errors.New(\"renaming assets in encrypted notebooks is not supported\")\n\t\t\treturn\n\t\t}\n\t}\n\n\tnewName = strings.TrimSpace(newName)\n\tnewName = util.FilterUploadFileName(newName)\n\tif path.Base(oldCleanPath) == newName {\n\t\treturn\n\t}\n\tif \"\" == newName {\n\t\treturn\n\t}\n\n\tif !gulu.File.IsValidFilename(newName) {\n\t\terr = errors.New(Conf.Language(151))\n\t\treturn\n\t}\n\n\tnewName = util.AssetName(newName+filepath.Ext(oldCleanPath), ast.NewNodeID())\n\tparentDir := path.Dir(oldCleanPath)\n\tnewPath = path.Join(parentDir, newName)\n\toldAbsPath, getErr := GetAssetAbsPathInBox(oldPath, \"\")\n\tif getErr != nil {\n\t\tlogging.LogErrorf(\"get asset [%s] abs path failed: %s\", oldPath, getErr)\n\t\treturn\n\t}\n\tif err = ensureReadableAssetLocal(oldAbsPath); err != nil {\n\t\treturn\n\t}\n\tnewAbsPath := filepath.Join(filepath.Dir(oldAbsPath), newName)\n\tfilelock.Lock(oldAbsPath)\n\tif err = os.Rename(oldAbsPath, newAbsPath); err != nil {\n\t\tif err = gulu.File.Copy(oldAbsPath, newAbsPath); err != nil {","sourceCodeStart":1651,"sourceCodeEnd":1687,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/assets.go#L1651-L1687","documentation":"The new asset name supplied to the rename API is not a valid filename according to gulu.File.IsValidFilename, so the kernel rejects it with a localized message (Conf.Language(151)). This guards against names containing path separators, reserved characters, or OS-illegal characters that could corrupt the assets tree.","triggerScenarios":"Calling model.RenameAsset with newName that is empty-after-trim pass but fails IsValidFilename — e.g. contains '/' or '\\\\', characters like ':' '*' '?' '\"' '<' '>' '|', leading/trailing dots, reserved Windows names (CON, NUL), or is too long.","commonSituations":"Pasting a filename copied from a URL or note text that includes slashes or illegal characters; renaming an asset to a Windows-reserved device name; automation scripts generating names without sanitization; localized UI message shown to end user.","solutions":["Provide a new name without path separators or reserved characters (letters, digits, spaces, hyphens, underscore, CJK text are fine)","Trim whitespace and remove illegal characters before calling the rename API","Sanitize with the same rules as util.FilterUploadFileName in scripts/plugins","If renaming to add an extension only, keep the base name valid — the kernel re-appends the original extension automatically"],"exampleFix":"// before\nrenameAsset('assets/old.png', 'chart: 2024/07.png')\n// after\nrenameAsset('assets/old.png', 'chart 2024-07.png')","handlingStrategy":"validation","validationCode":"const INVALID = /[\\\\/:*?\"<>|]/;\nfunction isValidAssetName(n) {\n  return typeof n === 'string' && n.trim().length > 0 && !INVALID.test(n) &&\n    !/^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])$/i.test(n.trim());\n}","typeGuard":"function isSafeFilename(v) {\n  return typeof v === 'string' && v.length > 0 && v.length < 255 && !/[\\\\/:*?\"<>|]/.test(v);\n}","tryCatchPattern":"if (!isSafeFilename(newName)) { showInvalidNameHint(); return; }\ntry { await renameAsset(oldPath, newName) } catch (e) {\n  if (e.message === Conf.Language(151)) showInvalidNameHint();\n}","preventionTips":["Sanitize names with the same rules as util.FilterUploadFileName","Reject path separators and Windows-reserved names in your UI before submitting","Preserve the original extension; the kernel appends it automatically"],"tags":["validation","filename","assets"],"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"}