siyuan-note/siyuan · error
invalid asset filename
Error message
invalid asset filename
What it means
Thrown by InsertAssetBytes when the filename, after sanitization by util.FilterUploadFileName and extension normalization, is empty, is just a dot, or has no extension. The function requires a valid base name with an extension to compute the on-disk asset filename via util.AssetName or encryptedAssetName.
Source
Thrown at kernel/model/upload.go:54
"github.com/siyuan-note/siyuan/kernel/util"
)
// InsertAssetBytes 将内存中的资源直接写入目标文档资源目录,避免生成内容经过明文临时文件。
func InsertAssetBytes(id, fileName string, data []byte) (assetPath string, created bool, err error) {
bt := treenode.GetBlockTree(id)
if bt == nil {
return "", false, errors.New(Conf.Language(71))
}
if len(data) == 0 {
return "", false, errors.New("asset data is empty")
}
baseName := filepath.Base(fileName)
fName := util.FilterUploadFileName(baseName)
ext := strings.ToLower(filepath.Ext(fName))
fName = strings.TrimSuffix(fName, filepath.Ext(fName)) + ext
if fName == "" || fName == "." || ext == "" {
return "", false, errors.New("invalid asset filename")
}
docDirLocalPath := filepath.Join(util.DataDir, bt.BoxID, path.Dir(bt.Path))
assetsDirPath := getAssetsDir(filepath.Join(util.DataDir, bt.BoxID), docDirLocalPath)
if err = os.MkdirAll(assetsDirPath, 0755); err != nil {
return "", false, err
}
reader := bytes.NewReader(data)
hash, err := util.GetEtagByHandle(reader, int64(len(data)))
if err != nil {
return "", false, err
}
if existAssetPath := GetAssetPathByHash(hash, bt.BoxID); existAssetPath != "" {
originalName := util.RemoveID(filepath.Base(existAssetPath))
if strings.EqualFold(fName, originalName) {
return strings.TrimPrefix(existAssetPath, "/"), false, nil
}View on GitHub (pinned to 251596fc0d)
Solutions
- Ensure the fileName parameter includes a proper extension (e.g., 'image.png')
- If the source filename is unreliable, derive the extension from the MIME type before calling InsertAssetBytes
- Sanitize the filename client-side and reject filenames without extensions before sending
Example fix
// before assetPath, _, err := model.InsertAssetBytes(id, "screenshot", data) // after ext := mimeToExt(mimeType) // e.g. "png" assetPath, _, err := model.InsertAssetBytes(id, "screenshot."+ext, data)
Defensive patterns
Strategy: validation
Validate before calling
ext := filepath.Ext(fileName)
if ext == "" {
ext = mimeToExt(contentType) // derive from MIME type
fileName = fileName + "." + ext
}
if fileName == "" || ext == "" {
return errors.New("asset filename must have a valid extension")
}
assetPath, _, err := model.InsertAssetBytes(id, fileName, data) Prevention
- Always include a file extension in asset filenames
- When the source filename is unreliable, derive the extension from the MIME/content-type
- Sanitize filenames client-side and reject those without extensions
When it happens
Trigger: Passing a fileName that is empty, consists only of invalid characters stripped by FilterUploadFileName, has no file extension, or normalizes to '.' after processing. Example: fileName = "..." or fileName = "file" (no extension).
Common situations: Client-side code constructs a filename programmatically and forgets the extension; a download pipeline strips the extension; the original filename contained only characters that FilterUploadFileName removes.
Related errors
- asset data is empty
- no file found
- field [file] or [url] must not be empty
- Failed to insert asset file, please reopen the document
- task list item marker length should be 1
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/999103b4cef6c30a.
Report an issue: GitHub.