siyuan-note/siyuan · error
path belongs to encrypted notebook [%s]
Error message
path belongs to encrypted notebook [%s]
What it means
Thrown by rejectEncryptedArchivePath (kernel/api/archive.go), a security guard on the archive/zip API. Before packaging anything, the kernel maps the absolute path to a notebook id with model.ExtractBoxIDFromAssetsPath and checks model.IsEncryptedBox. If the path sits inside an encrypted notebook, the zip request is refused outright because the archive API is not encryption-aware and would copy ciphertext out of the protected store.
Source
Thrown at kernel/api/archive.go:35
package api
import (
"fmt"
"net/http"
"path/filepath"
"github.com/88250/gulu"
"github.com/gin-gonic/gin"
"github.com/siyuan-note/logging"
"github.com/siyuan-note/siyuan/kernel/model"
"github.com/siyuan-note/siyuan/kernel/util"
)
// rejectEncryptedArchivePath 检查路径是否落入加密笔记本目录(含 symlink 绕过),是则返回错误。
func rejectEncryptedArchivePath(absPath string) error {
boxID := model.ExtractBoxIDFromAssetsPath(absPath)
if boxID != "" && model.IsEncryptedBox(boxID) {
return fmt.Errorf("path belongs to encrypted notebook [%s]", boxID)
}
if resolved := util.ResolveLongestExistingParent(absPath); resolved != absPath {
boxID = model.ExtractBoxIDFromAssetsPath(resolved)
if boxID != "" && model.IsEncryptedBox(boxID) {
return fmt.Errorf("symlink resolves into encrypted notebook [%s]", boxID)
}
}
return nil
}
func zip(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)
arg, ok := util.JsonArg(c, ret)
if !ok {
return
}View on GitHub (pinned to afa823b6b4)
Solutions
- Export the encrypted notebook through the dedicated export APIs, which acquire the box lease and decrypt content properly (they route through holdEncryptedBoxRequest)
- Move or keep the files you need to archive in a non-encrypted notebook
- Scope the zip path to exclude the encrypted notebook's directory and archive the remaining notebooks
- Do not attempt to zip encrypted notebook paths directly; the guard is intentional and has no override flag
Defensive patterns
Strategy: validation
Validate before calling
function isEncryptedBoxId(boxId: string, notebooks: { id: string; encrypted: boolean }[]): boolean {
return notebooks.some(n => n.id === boxId && n.encrypted);
}
// before archiving a path:
const box = boxIdFromAssetsPath(absPath);
const nb = await fetchGet('/api/notebook/lsNotebooks');
if (box && isEncryptedBoxId(box, nb.data.notebooks)) {
throw new Error('skip encrypted notebook in archive job');
} Type guard
const isEncryptedNotebookPath = (absPath: string, encryptedBoxIds: Set<string>): boolean => {
const m = absPath.match(/data\/([0-9]{14}[^\/]*)\/assets\//); // box id from assets path
return !!m && encryptedBoxIds.has(m[1]);
}; Try / catch
if (res.code === -1 && res.msg.startsWith('path belongs to encrypted notebook')) {
// exclude the encrypted notebook's subtree from the archive scope and re-run
} Prevention
- Maintain the encrypted-notebook id set and filter archive jobs against it up front
- Use the dedicated export flow for encrypted notebooks; never zip their directories directly
- Document that the archive API is not encryption-aware so automation authors do not rediscover this
When it happens
Trigger: Calling the archive zip endpoint with a path under an encrypted notebook's directory (its assets or notebook folder), regardless of whether the notebook is currently unlocked; scripting a bulk zip of the whole workspace while at least one encrypted notebook exists under the tree.
Common situations: Encrypted-notebook feature enabled and an export/backup tool or plugin zips workspace paths; automated backup scripts that walk data/ and hit the encrypted notebook dir; users trying to hand-archive an encrypted notebook via the generic archive API instead of the dedicated export flow.
Related errors
- symlink resolves into encrypted notebook [%s]
- encrypted notebook is locked, please unlock it first
- refuse to write decrypted asset inside workspace
- source is not an encrypted asset
- encrypted notebook is locked, please unlock it first
AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18).
Data as JSON: /api/errors/d21750adeba9cd22.
Report an issue: GitHub.