{"record":{"id":"99baafff36b06cc8","repo":"siyuan-note/siyuan","slug":"d-asset-upload-s-failed","errorCode":null,"errorMessage":"%d asset upload(s) failed","messagePattern":"(.+?) asset upload\\(s\\) failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/cli/cmd/asset.go","lineNumber":105,"sourceCode":"\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tfiles[i] = abs\n\t\t}\n\n\t\tif dryRun {\n\t\t\tfmt.Printf(\"[dry-run] Would upload %d file(s) to document %s\\n\", len(files), id)\n\t\t\treturn nil\n\t\t}\n\n\t\t_, succFiles, failedFiles, err := model.InsertLocalAssets(id, files, true)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tresult := newAssetUploadCommandOutput(succFiles, failedFiles)\n\t\tprintAssetUploadCommandOutput(result)\n\t\tif 0 < len(failedFiles) {\n\t\t\treturn fmt.Errorf(\"%d asset upload(s) failed\", len(failedFiles))\n\t\t}\n\t\treturn nil\n\t},\n}\n\nvar assetUnusedCmd = &cobra.Command{\n\tUse:   \"unused\",\n\tShort: \"List unused assets\",\n\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\titems := model.UnusedAssets(true)\n\t\tswitch outputFormat {\n\t\tcase \"json\":\n\t\t\tdata, _ := json.MarshalIndent(items, \"\", \"  \")\n\t\t\tfmt.Println(string(data))\n\t\tdefault:\n\t\t\tif len(items) == 0 {\n\t\t\t\tfmt.Println(\"No unused assets found.\")\n\t\t\t\treturn nil","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/cli/cmd/asset.go#L87-L123","documentation":"After printing the per-file upload results, the `asset upload` command returns an aggregate error when any uploads failed, summarizing the count. The command is still a failure exit even though some files succeeded — check the printed per-file output for which paths failed and why.","triggerScenarios":"Running `asset upload` where at least one --file path failed — nonexistent source path, unreadable file, network/kernel API error during upload, or an invalid target id.","commonSituations":"Batch scripts uploading many files where one was locked/deleted mid-run; a typo in one path among many; kernel unreachable or auth expired partway through the batch; asset size or type rejected by the kernel.","solutions":["Read the printed upload report (printAssetUploadCommandOutput) to identify the failed paths and their reasons","Fix each failed file (missing path, permissions) or correct the target --id and re-run the upload for those files only","Check kernel connectivity/auth if many files failed at once","Make the script tolerant: treat the non-zero exit as 'partial success' and retry only the failed subset"],"exampleFix":"// before\nsiyuan asset upload --id $ID --file a.png --file b.png  # exits 1: '1 asset upload(s) failed'\n// after (retry only failures identified from the printed report)\nsiyuan asset upload --id $ID --file a.png --file b.png || {\n  siyuan asset upload --id $ID --file b.png\n}","handlingStrategy":"try-catch","validationCode":"for f in \"${files[@]}\"; do\n  [ -r \"$f\" ] || echo \"warning: $f is not readable and will fail upload\"\ndone","typeGuard":null,"tryCatchPattern":"if err := assetUploadCmd.Execute(); err != nil {\n    if strings.Contains(err.Error(), \"asset upload(s) failed\") {\n        // parse printed report for failedFiles and retry them individually\n        os.Exit(1)\n    }\n    panic(err)\n}","preventionTips":["Pre-verify every --file path exists and is readable before running the batch","Upload in small batches so one bad file doesn't obscure others","Keep the command output — it is the only record of which files failed"],"tags":["cli","upload","batch"],"backgroundTag":"api-error-response","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}