siyuan-note/siyuan · error
asset data is empty
Error message
asset data is empty
What it means
InsertAssetBytes rejects an empty byte slice. An asset with zero bytes has no meaningful content (and would break hashing/dedup), so the kernel fails fast instead of writing a 0-byte file into the assets directory.
Solutions
- Check len(data) > 0 in the caller before calling InsertAssetBytes and treat an empty buffer as an upstream failure
- Fix the producer of the bytes (re-download the image, re-run the generator) — the empty payload is the real bug
- Verify the source file is not 0 bytes (os.Stat before reading)
- Log the upstream step's error instead of discarding it; an empty body usually masks an earlier failed read
Example fix
// before
assetPath, _, _ := model.InsertAssetBytes(id, name, data)
// after
if len(data) == 0 {
return errors.New("asset source returned empty data; aborting insert")
}
assetPath, _, err := model.InsertAssetBytes(id, name, data) Defensive patterns
Strategy: validation
Validate before calling
if data == nil || len(data) == 0 {
return errors.New("refusing to insert empty asset payload")
} Try / catch
assetPath, _, err := model.InsertAssetBytes(id, name, data)
if err != nil && strings.Contains(err.Error(), "asset data is empty") {
// propagate upstream producer failure; do not retry with the same empty buffer
} Prevention
- Check len(data) > 0 before every insert call
- Verify source files are non-empty with os.Stat before reading
- Never swallow errors from the step that produces the bytes — empty payloads usually mask an earlier failure
When it happens
Trigger: Calling InsertAssetBytes with data == nil or len(data) == 0 — e.g. a read of the source image/attachment returned no bytes, a truncated download was passed through, or the caller sliced an empty buffer.
Common situations: AI/image generation returned no payload; reading a file that is 0 bytes on disk; a download error swallowed earlier and an empty body propagated to the insert step.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- AI editor input is empty
- at least one asset path or mapping is required
- Conf.Language(294)
- createDocTree document list must not be empty
- createDocTree requires at least one document
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/26311b8fad7ad4e3.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/upload.go:47
"github.com/88250/gulu"
"github.com/88250/lute/ast"
"github.com/gin-gonic/gin"
"github.com/siyuan-note/filelock"
"github.com/siyuan-note/logging"
"github.com/siyuan-note/siyuan/kernel/cache"
"github.com/siyuan-note/siyuan/kernel/treenode"
"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)))View on GitHub (pinned to 9f775e8a12)