{"record":{"id":"26311b8fad7ad4e3","repo":"siyuan-note/siyuan","slug":"asset-data-is-empty","errorCode":null,"errorMessage":"asset data is empty","messagePattern":"asset data is empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/upload.go","lineNumber":47,"sourceCode":"\n\t\"github.com/88250/gulu\"\n\t\"github.com/88250/lute/ast\"\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/siyuan-note/filelock\"\n\t\"github.com/siyuan-note/logging\"\n\t\"github.com/siyuan-note/siyuan/kernel/cache\"\n\t\"github.com/siyuan-note/siyuan/kernel/treenode\"\n\t\"github.com/siyuan-note/siyuan/kernel/util\"\n)\n\n// InsertAssetBytes 将内存中的资源直接写入目标文档资源目录，避免生成内容经过明文临时文件。\nfunc InsertAssetBytes(id, fileName string, data []byte) (assetPath string, created bool, err error) {\n\tbt := treenode.GetBlockTree(id)\n\tif bt == nil {\n\t\treturn \"\", false, errors.New(Conf.Language(71))\n\t}\n\tif len(data) == 0 {\n\t\treturn \"\", false, errors.New(\"asset data is empty\")\n\t}\n\n\tbaseName := filepath.Base(fileName)\n\tfName := util.FilterUploadFileName(baseName)\n\text := strings.ToLower(filepath.Ext(fName))\n\tfName = strings.TrimSuffix(fName, filepath.Ext(fName)) + ext\n\tif fName == \"\" || fName == \".\" || ext == \"\" {\n\t\treturn \"\", false, errors.New(\"invalid asset filename\")\n\t}\n\n\tdocDirLocalPath := filepath.Join(util.DataDir, bt.BoxID, path.Dir(bt.Path))\n\tassetsDirPath := getAssetsDir(filepath.Join(util.DataDir, bt.BoxID), docDirLocalPath)\n\tif err = os.MkdirAll(assetsDirPath, 0755); err != nil {\n\t\treturn \"\", false, err\n\t}\n\n\treader := bytes.NewReader(data)\n\thash, err := util.GetEtagByHandle(reader, int64(len(data)))","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/upload.go#L29-L65","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nassetPath, _, _ := model.InsertAssetBytes(id, name, data)\n// after\nif len(data) == 0 {\n    return errors.New(\"asset source returned empty data; aborting insert\")\n}\nassetPath, _, err := model.InsertAssetBytes(id, name, data)","handlingStrategy":"validation","validationCode":"if data == nil || len(data) == 0 {\n    return errors.New(\"refusing to insert empty asset payload\")\n}","typeGuard":null,"tryCatchPattern":"assetPath, _, err := model.InsertAssetBytes(id, name, data)\nif err != nil && strings.Contains(err.Error(), \"asset data is empty\") {\n    // propagate upstream producer failure; do not retry with the same empty buffer\n}","preventionTips":["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"],"tags":["validation","empty-input","asset"],"backgroundTag":"empty-required-field","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}