siyuan-note/siyuan · error
Conf.Language(314)
Error message
Conf.Language(314)
What it means
withExportReadLockByBlockID guards all export entry points (ExportCodeBlock, ExportAv2CSV, Export2Liandi, ExportPreview, ExportDocx, exportMarkdownHTML) against operating on encrypted notebooks. If the target block's box is encrypted and currently locked (IsBoxUnlocked false), it returns Conf.Language(314): 'Please unlock the encrypted notebook first'.
Source
Thrown at kernel/model/export.go:614
// 用于文档级导出入口的统一 guard,避免未解锁时读出密文或空结果。
func exportLockedByBlockID(id string) bool {
bt := getExportBlockTree(id)
if nil == bt {
return false // 找不到块树,交给后续流程处理
}
return IsEncryptedBox(bt.BoxID) && !IsBoxUnlocked(bt.BoxID)
}
// withExportReadLockByBlockID 由 blockID 反查 boxID,若属于加密笔记本则全程持读锁执行 fn。
// 持锁期间 LockBox(自动锁定)会阻塞等待,避免操作中途清 DEK/删导出目录导致部分明文写出。
// 准入租约先于读锁取得,确保嵌套资源读取期间不会出现等待中的写锁。
func withExportReadLockByBlockID(id string, fn func() error) error {
bt := getExportBlockTree(id)
if nil == bt || !IsEncryptedBox(bt.BoxID) {
return fn()
}
if !IsBoxUnlocked(bt.BoxID) {
return errors.New(Conf.Language(314))
}
if err := AcquireEncryptedBoxOperation(bt.BoxID); err != nil {
return errors.New(Conf.Language(314))
}
defer ReleaseEncryptedBoxOperation(bt.BoxID)
HoldBoxReadLock(bt.BoxID)
defer ReleaseBoxReadLock(bt.BoxID)
dek, dekErr := GetDEKIfUnlocked(bt.BoxID)
if dekErr != nil {
return errors.New(Conf.Language(314))
}
clear(dek)
return fn()
}
func ExportNotebookSY(id string) (zipPath string) {
// 加密笔记本必须已解锁才能导出(DEK 在内存才能读 .sy/assets/AV 明文)
if IsEncryptedBox(id) && !IsBoxUnlocked(id) {View on GitHub (pinned to 8641553a1f)
Solutions
- Unlock the encrypted notebook via the UI (enter passphrase) and retry the export
- Call the kernel unlock API for the box before invoking the export endpoint
Example fix
// before await exportDocx(blockId) // box still locked after restart // after await unlockBox(boxId) // provide passphrase first await exportDocx(blockId)
Defensive patterns
Strategy: validation
Validate before calling
const boxEncrypted = await isEncryptedBox(boxOf(blockId));
const unlocked = boxEncrypted ? await isBoxUnlocked(boxOf(blockId)) : true;
if (!unlocked) throw new Error("Unlock the encrypted notebook before exporting"); Try / catch
try {
await exportDocx(blockId);
} catch (e) {
if (String(e.msg).includes("unlock")) showUnlockDialog();
} Prevention
- Check box encryption/lock state via kernel API before any export call
- After kernel restart, prompt users to unlock encrypted notebooks before enabling export actions
When it happens
Trigger: Any of the six export APIs called with a block ID whose parent box is an encrypted notebook that has not been unlocked in this session.
Common situations: User restarts SiYuan (keys locked) and immediately exports a doc from an encrypted notebook; headless/API scripts running without having supplied the encryption passphrase.
Related errors
- Please unlock the encrypted notebook first
- Conf.Language(314)
- Related operations are being processed, please try again lat
- Please unlock the encrypted notebook first
- Please unlock the encrypted notebook first
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/6702a2e312d83cc2.
Report an issue: GitHub.