siyuan-note/siyuan · warning
asset is not unused: %s
Error message
asset is not unused: %s
What it means
Thrown by ResolveUnusedDataAssetPath (kernel/model/assets.go:989) after the path resolved successfully but the asset is NOT present in the computed unused-asset list (UnusedAssets(false)). It is a business-rule guard, not a security or filesystem error: the caller asked to operate on an unused asset, but the asset is still referenced by some block, so the operation is refused.
Source
Thrown at kernel/model/assets.go:989
err = fmt.Errorf("asset path resolves outside assets directory: %s", assetPath)
return
}
relativePath = filepath.ToSlash(dataRelativePath)
return
}
// ResolveUnusedDataAssetPath 解析 data 相对资源路径,并确认目标当前未被引用。
func ResolveUnusedDataAssetPath(assetPath string) (relativePath, absPath string, err error) {
relativePath, absPath, err = ResolveDataAssetPath(assetPath)
if err != nil {
return
}
if unusedAssetsContainPath(relativePath, absPath, UnusedAssets(false)) {
return
}
err = fmt.Errorf("asset is not unused: %s", relativePath)
return
}
func unusedAssetsContainPath(relativePath, absPath string, items []*UnusedItem) bool {
resolvedPath, _ := filepath.EvalSymlinks(absPath)
for _, item := range items {
if item.AbsPath != "" {
resolvedItemPath, evalErr := filepath.EvalSymlinks(item.AbsPath)
samePath, relErr := filepath.Rel(resolvedPath, resolvedItemPath)
if resolvedPath != "" && evalErr == nil && relErr == nil && samePath == "." {
return true
}
continue
}
itemPath := filepath.ToSlash(filepath.Clean(filepath.FromSlash(item.Item)))
if itemPath == relativePath {
return true
}View on GitHub (pinned to 251596fc0d)
Solutions
- Confirm the asset is genuinely unused: search the notebook for the filename and remove/replace every reference.
- Force the unused-asset index to refresh (re-index the relevant notebooks) so references are accurately counted, then retry.
- If you must remove a still-referenced asset, use the explicit delete API (which will also rewrite references) rather than the unused-asset path.
- Do not catch-and-ignore; removing a referenced asset would create broken links.
Defensive patterns
Strategy: validation
Validate before calling
// Confirm the asset is in the unused set before attempting an unused-asset operation.
unused := model.UnusedAssets(false)
found := false
for _, it := range unused {
if it.Item == p || it.AbsPath == abs { found = true; break }
}
if !found { return fmt.Errorf("asset %s is still referenced; use the referenced-asset delete path", p) } Try / catch
if _, _, err := model.ResolveUnusedDataAssetPath(p); err != nil {
if strings.Contains(err.Error(), "not unused") {
// still referenced — re-index, then retry, or use the explicit delete API that rewrites references
}
} Prevention
- Re-index notebooks before cleanup so the unused-asset list is accurate.
- Prefer the explicit delete API when you know references exist, so links are rewritten.
- Do not catch-and-delete anyway; that creates broken asset references.
When it happens
Trigger: Calling ResolveUnusedDataAssetPath (used by cli/cmd/asset.go:120 for `siyuan asset` cleanup and by model.RemoveUnusedAsset / assets.go:1446) with an asset path whose file is still referenced in at least one document. The unused-asset scan re-checks references, and because the asset is referenced, it is absent from the unused list.
Common situations: Running a cleanup/delete on an asset the user believes is unused but is still embedded in a note; a reference that was thought to be deleted but remains in the blocktree (stale SQL rows not yet flushed); calling cleanup right after re-linking the asset elsewhere.
Related errors
- assetPath is required for analyze
- only local assets/... images are supported
- assetPath is not an image referenced by the document
- asset path is required
- asset path must be relative to data directory: %s
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/7c5ef8db631fd506.
Report an issue: GitHub.