siyuan-note/siyuan · error
Conf.Language(151) (localized invalid filename message)
Error message
Conf.Language(151) (localized invalid filename message)
What it means
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.
Source
Thrown at kernel/model/assets.go:1665
// 加密笔记本的资源磁盘文件名参与 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
}
if err = ensureReadableAssetLocal(oldAbsPath); err != nil {
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 {View on GitHub (pinned to 8641553a1f)
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.
Example fix
// before renameAsset(oldPath, "report/2026: final?") // rejected // after renameAsset(oldPath, "report-2026-final") // valid filename
Defensive patterns
Strategy: validation
Validate before calling
const FORBIDDEN = /[/\\:*?"<>|\u0000-\u001f]/;
function isValidNewAssetName(name) {
return typeof name === 'string' && name.trim().length > 0 && !FORBIDDEN.test(name.trim());
}
if (!isValidNewAssetName(newName)) throw new Error('invalid filename'); Type guard
function isSafeFilename(v) {
return typeof v === 'string' && v.trim().length > 0 && !/[/\\:*?"<>|]/.test(v.trim());
} Try / catch
try {
await fetchPost('/api/asset/renameAsset', {oldPath, newName});
} catch (e) {
if (isInvalidFilenameError(e)) {
showInputError('Name contains forbidden characters or is empty');
}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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).
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Do not include symbols \ / : * ? " ' < > |
- invalid asset filename
- Cannot create a file starting with .
- Do not include Markdown syntax marker [%s]
- Tag cannot be empty
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/b2d23ac265b82bb5.
Report an issue: GitHub.