siyuan-note/siyuan · warning
Do not include symbols \ / : * ? " ' < > |
Error message
Do not include symbols \ / : * ? " ' < > |
What it means
RenameAsset validates the filtered new name with gulu.File.IsValidFilename; if it still contains any reserved character - backslash, slash, colon, asterisk, question mark, double quote, apostrophe, less-than, greater-than, pipe - the localized message listing the symbols (Conf.Language(151)) is returned and the rename is refused.
Solutions
- Remove the listed symbols from the new name and retry
- Pre-validate the input in the UI before submitting the rename
- Omit the file extension - the kernel appends the old extension automatically
Example fix
// before
newPath, err := model.RenameAsset(oldPath, "report: 2024?")
// after: sanitize first
newName = strings.TrimSpace(newName)
for _, r := range `\/:*?"'<>|` {
newName = strings.ReplaceAll(newName, string(r), "")
}
newPath, err := model.RenameAsset(oldPath, newName) Defensive patterns
Strategy: validation
Validate before calling
newName = strings.TrimSpace(util.FilterUploadFileName(newName))
if !gulu.File.IsValidFilename(newName) {
// reject in the UI before calling model.RenameAsset
} Type guard
func isValidNewAssetName(s string) bool {
s = strings.TrimSpace(s)
if s == "" {
return false
}
for _, r := range `\/:*?"'<>|` {
if strings.ContainsRune(s, r) {
return false
}
}
return true
} Try / catch
Check err from RenameAsset and keep the rename dialog open with the invalid characters highlighted so the user can correct the name; retry only after re-validation.
Prevention
- Validate filenames client-side with the same character set
- Strip extensions from user input - the kernel re-appends it
- Normalize pasted titles before using them as asset names
When it happens
Trigger: Calling rename with a newName that still contains any of \ / : * ? " ' < > | after util.FilterUploadFileName trimming; commonly names pasted from web page titles.
Common situations: Pasting titles like 'Report: 2024?' as asset names; cross-platform names with characters Windows forbids.
Related errors
- Conf.Language(151) (localized invalid filename message)
- 106
- Cannot create a file starting with .
- Conf.Language(106)
- Conf.Language(142)
AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18).
Data as JSON: /api/errors/79a11266783fb174.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/assets.go:1547
// 加密笔记本的资源磁盘文件名参与 AAD,重命名需要重新封装密文,当前不支持。
if absPath, absErr := GetAssetAbsPathInBox(oldPath, ""); absErr == nil {
if IsEncryptedAssetPath(absPath) {
err = errors.New("renaming assets in encrypted notebooks is not supported")
return
}
}
newName = strings.TrimSpace(newName)
newName = util.FilterUploadFileName(newName)
if path.Base(oldCleanPath) == newName {
return
}
if "" == newName {
return
}
if !gulu.File.IsValidFilename(newName) {
err = errors.New(Conf.Language(151))
return
}
newName = util.AssetName(newName+filepath.Ext(oldCleanPath), ast.NewNodeID())
parentDir := path.Dir(oldCleanPath)
newPath = path.Join(parentDir, newName)
oldAbsPath, getErr := GetAssetAbsPathInBox(oldPath, "")
if getErr != nil {
logging.LogErrorf("get asset [%s] abs path failed: %s", oldPath, getErr)
return
}
newAbsPath := filepath.Join(filepath.Dir(oldAbsPath), newName)
filelock.Lock(oldAbsPath)
if err = os.Rename(oldAbsPath, newAbsPath); err != nil {
if err = gulu.File.Copy(oldAbsPath, newAbsPath); err != nil {
filelock.Unlock(oldAbsPath)
logging.LogErrorf("copy asset [%s] failed: %s", oldAbsPath, err)
returnView on GitHub (pinned to afa823b6b4)