siyuan-note/siyuan · error
walk global assets [%s] failed: %w
Error message
walk global assets [%s] failed: %w
What it means
The kernel failed while walking the global data/assets directory to build a map of asset paths (used by asset cleanup/refresh operations such as RemoveUnusedAssets). filepath.Walk returned a non-nil, non-not-exist error (e.g. permission denied on a subdirectory or I/O error on an entry), which is wrapped with the assets directory path for context. If the directory simply does not exist the walk is treated as a no-op, so this error means a real filesystem failure occurred during traversal.
Source
Thrown at kernel/model/assets.go:2815
}
if filelock.IsHidden(assetPath) {
// 清理资源文件时忽略隐藏文件 Ignore hidden files when cleaning unused assets https://github.com/siyuan-note/siyuan/issues/12172
return nil
}
relPath, relErr := assetPathMapKey(dataAssetsAbsPath, assetPath, d.IsDir())
if relErr != nil {
return relErr
}
assetsAbsPathMap[relPath] = assetPath
return nil
})
if walkErr != nil {
if os.IsNotExist(walkErr) {
return
}
return nil, fmt.Errorf("walk global assets [%s] failed: %w", dataAssetsAbsPath, walkErr)
}
return
}
func assetPathMapKey(assetsDirPath, assetPath string, isDir bool) (ret string, err error) {
relPath, err := filepath.Rel(assetsDirPath, assetPath)
if err != nil {
return
}
relPath = filepath.ToSlash(relPath)
if relPath == "." || relPath == ".." || strings.HasPrefix(relPath, "../") || path.IsAbs(relPath) {
err = fmt.Errorf("asset path [%s] is outside assets directory [%s]", assetPath, assetsDirPath)
return
}
ret = path.Join("assets", relPath)
if isDir {
ret += "/"View on GitHub (pinned to 8641553a1f)
Solutions
- Check permissions on data/assets and its children (chmod/chown so the kernel user can read everything).
- Run with the message's wrapped cause: the %w suffix names the underlying walk error (e.g. 'permission denied' on a specific path) and fix that path.
- Exclude or remove broken entries (dead symlinks, locked files) under data/assets.
- If the directory is intentionally absent, no action is needed — a missing data/assets is silently tolerated; only fix cases where it exists but is unreadable.
Example fix
// before (server container): data/assets owned by root, kernel runs as siyuan // walk global assets [/siyuan/data/assets] failed: open /siyuan/data/assets/sub: permission denied // after: fix ownership/permissions on the host or in the container image chown -R siyuan:siyuan /siyuan/data/assets chmod -R u+rX /siyuan/data/assets
Defensive patterns
Strategy: try-catch
Validate before calling
const fs = require('fs');
function assertAssetsReadable(dir) {
if (!fs.existsSync(dir)) return; // missing dir is tolerated by the kernel
fs.accessSync(dir, fs.constants.R_OK | fs.constants.X_OK);
for (const e of fs.readdirSync(dir)) fs.accessSync(path.join(dir, e), fs.constants.R_OK);
} Try / catch
try {
await api.removeUnusedAssets();
} catch (e) {
if (/walk global assets .* failed/.test(e.message)) {
console.error("Check permissions/locks under data/assets:", e.cause ?? e.message);
}
} Prevention
- Run the kernel under a user that owns or can read data/assets recursively.
- Exclude data/assets from tools that lock or scan files (antivirus, backup agents).
- Avoid symlinks inside data/assets pointing outside the workspace.
- Monitor for unreadable entries after restores or cloud-sync merges.
When it happens
Trigger: Calling asset cleanup paths (e.g. the API that removes unused assets) when a file or subdirectory under data/assets cannot be read: unreadable directory permissions, symlink loops, I/O errors, or a race where a file is removed mid-walk.
Common situations: Running the kernel in a container where data/assets was mounted with restrictive permissions; an antivirus or backup tool locking files on Windows; a partially-synced cloud-drive folder producing broken entries under data/assets.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- walk notebook assets [%s] failed: %w
- asset path does not belong to a notebook: %s
- resolve assets directory [%s] failed: %w
- Conf.Language(0) (localized open notebook failure message)
- copy unused asset [%s] to history failed: %w
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/daf0cc9c3eeedd2a.
Report an issue: GitHub.