{"record":{"id":"b2d23ac265b82bb5","repo":"siyuan-note/siyuan","slug":"conf-language-151-localized-invalid-filename-mes","errorCode":null,"errorMessage":"Conf.Language(151) (localized invalid filename message)","messagePattern":"Conf\\.Language\\(151\\) \\(localized invalid filename message\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/assets.go","lineNumber":1665,"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":1647,"sourceCodeEnd":1683,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/assets.go#L1647-L1683","documentation":"During RenameAsset, after trimming and filtering the requested new name, it is validated with gulu.File.IsValidFilename. If the resulting name is empty after filtering or contains characters invalid for a filename on supported platforms, the function returns Conf.Language(151), the localized \"invalid filename\" message, and aborts the rename.","triggerScenarios":"Calling the asset-rename API with a newName that is empty, contains forbidden characters (e.g. \\/:*?\"<>| or control chars), is a reserved name, or reduces to empty after util.FilterUploadFileName strips invalid parts.","commonSituations":"Users typing names with slashes or OS-reserved characters; copy-pasting titles containing illegal characters; submitting an empty name; names consisting only of characters the filter removes (spaces/dots).","solutions":["Provide a new name containing only valid filename characters (letters, digits, CJK, hyphen, underscore).","Avoid path separators and OS-reserved characters like / \\ : * ? \" < > |.","Ensure the name is non-empty after trimming; a whitespace-only name is rejected.","Strip or replace forbidden characters before calling the API instead of relying on the filter to fail."],"exampleFix":"// before\nrenameAsset(oldPath, \"report/2026: final?\")   // rejected\n// after\nrenameAsset(oldPath, \"report-2026-final\")     // valid filename","handlingStrategy":"validation","validationCode":"const FORBIDDEN = /[/\\\\:*?\"<>|\\u0000-\\u001f]/;\nfunction isValidNewAssetName(name) {\n  return typeof name === 'string' && name.trim().length > 0 && !FORBIDDEN.test(name.trim());\n}\nif (!isValidNewAssetName(newName)) throw new Error('invalid filename');","typeGuard":"function isSafeFilename(v) {\n  return typeof v === 'string' && v.trim().length > 0 && !/[/\\\\:*?\"<>|]/.test(v.trim());\n}","tryCatchPattern":"try {\n  await fetchPost('/api/asset/renameAsset', {oldPath, newName});\n} catch (e) {\n  if (isInvalidFilenameError(e)) {\n    showInputError('Name contains forbidden characters or is empty');\n  }\n}","preventionTips":["Validate the name client-side before calling the rename API","Sanitize pasted titles: strip path separators and reserved characters","Reject empty or whitespace-only names early","Test names on both Windows and Unix reserved-character sets"],"tags":["filename","validation","rename","assets"],"backgroundTag":"invalid-argument-value","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}