siyuan-note/siyuan · error
accessing assets in encrypted notebook [%s] is not supported
Error message
accessing assets in encrypted notebook [%s] is not supported
What it means
Returned by ResolveDataAssetPath when the notebook identified by the first path segment is encrypted (IsEncryptedBox returns true). ResolveDataAssetPath deliberately refuses to resolve assets inside encrypted notebooks — encrypted assets are accessed through ReadAssetBytesInBox (which decrypts), not through this generic resolver. The notebook ID is interpolated.
Source
Thrown at kernel/model/assets.go:932
assetDirIndex := -1
switch {
case len(parts) > 1 && parts[0] == "assets":
assetDirIndex = 0
case len(parts) > 2 && ast.IsNodeIDPattern(parts[0]):
for i := 1; i < len(parts)-1; i++ {
if parts[i] == "assets" {
assetDirIndex = i
break
}
}
if assetDirIndex > 0 {
boxConfPath := filepath.Join(util.DataDir, parts[0], ".siyuan", "conf.json")
if !filelock.IsExist(boxConfPath) {
err = fmt.Errorf("asset path does not belong to a notebook: %s", assetPath)
return
}
if IsEncryptedBox(parts[0]) {
err = fmt.Errorf("accessing assets in encrypted notebook [%s] is not supported", parts[0])
return
}
}
}
if assetDirIndex < 0 {
err = fmt.Errorf("path is not under an assets directory: %s", assetPath)
return
}
assetRootParts := parts[:assetDirIndex+1]
assetRoot := filepath.Join(util.DataDir, filepath.FromSlash(strings.Join(assetRootParts, "/")))
if !gulu.File.IsSubPath(assetRoot, absPath) {
err = fmt.Errorf("path is not a child of assets directory: %s", assetPath)
return
}
resolvedRoot, evalErr := filepath.EvalSymlinks(assetRoot)
if evalErr != nil {View on GitHub (pinned to 251596fc0d)
Solutions
- For encrypted-notebook assets, use ReadAssetBytesInBox(boxID, relativePath) instead, which acquires the read lock and decrypts.
- Ensure the notebook is unlocked in this session before reading.
- Route encrypted-asset access through APIs that are encryption-aware, not through ResolveDataAssetPath.
Example fix
// before — generic resolver rejects encrypted notebook
rel, abs, err := model.ResolveDataAssetPath("<encBoxID>/assets/x.png")
// after — use the encryption-aware read path
data, err := model.ReadAssetBytesInBox("<encBoxID>", "assets/x.png") Defensive patterns
Strategy: validation
Validate before calling
parts := strings.Split(filepath.ToSlash(filepath.Clean(assetPath)), "/")
if len(parts) > 2 && ast.IsNodeIDPattern(parts[0]) && model.IsEncryptedBox(parts[0]) {
// route to the encryption-aware API instead
return model.ReadAssetBytesInBox(parts[0], assetPath)
} Prevention
- Use ReadAssetBytesInBox for encrypted-notebook assets — it decrypts correctly.
- Do not route encrypted-asset access through generic resolvers.
- Ensure the encrypted notebook is unlocked in the session.
When it happens
Trigger: Calling ResolveDataAssetPath with a path whose notebook prefix is an encrypted notebook, e.g. "<encBoxID>/assets/x.png?box=<encBoxID>". This is by-design enforcement, not a transient error.
Common situations: Generic asset tooling (thumbnails, export, search-asset-content) tries to touch an encrypted notebook's assets without going through the encryption-aware read path.
Related errors
- encrypted notebook is locked, please unlock it first
- CLI does not support encrypted notebook [%s]
- CLI does not support files in encrypted notebooks
- path belongs to encrypted notebook [%s]: %s
- renaming assets in encrypted notebooks is not supported
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/f9c390e75f91e57d.
Report an issue: GitHub.