siyuan-note/siyuan · warning
encrypted notebook is not unlocked
Error message
encrypted notebook is not unlocked
What it means
`ErrEncryptedBoxNotUnlocked` is the sentinel error returned when an operation tries to acquire a lease on an encrypted notebook whose lifecycle state is not `EncryptedBoxStateUnlocked` or which is not currently accepting operations. It signals that the notebook must be unlocked (typically with the master password) before the requested operation can proceed.
Source
Thrown at kernel/model/crypto_lifecycle.go:203
lifecycle.acceptOperations = false
for lifecycle.activeOperations > 0 {
lifecycle.condition.Wait()
}
lifecycle.lock.Unlock()
}
type encryptedBoxOperationScope struct {
lock sync.Mutex
boxIDs []string
boxIDSet map[string]struct{}
closed bool
}
type encryptedBoxOperationScopeKey struct{}
var (
// ErrEncryptedBoxNotUnlocked 表示加密笔记本当前未解锁。
ErrEncryptedBoxNotUnlocked = errors.New("encrypted notebook is not unlocked")
// ErrEncryptedBoxOperationScopeClosed 表示响应级操作作用域已经关闭。
ErrEncryptedBoxOperationScopeClosed = errors.New("encrypted notebook operation scope is closed")
)
// WithEncryptedBoxOperationScope 创建覆盖整个外层响应过程的租约作用域。
func WithEncryptedBoxOperationScope(ctx context.Context) (context.Context, func()) {
scope := &encryptedBoxOperationScope{boxIDSet: map[string]struct{}{}}
scopedContext := context.WithValue(ctx, encryptedBoxOperationScopeKey{}, scope)
return scopedContext, scope.release
}
// AcquireEncryptedBoxOperations 按固定顺序取得多个笔记本的响应级租约。
func AcquireEncryptedBoxOperations(ctx context.Context, boxIDs []string) (release func(), err error) {
unique := map[string]struct{}{}
for _, boxID := range boxIDs {
if boxID != "" && IsEncryptedBox(boxID) {
unique[boxID] = struct{}{}
}View on GitHub (pinned to 8641553a1f)
Solutions
- Unlock the encrypted notebook first via the unlock API/UI with the master password, then retry the operation.
- Check errors.Is(err, model.ErrEncryptedBoxNotUnlocked) and surface a user-facing 'please unlock' message as the MCP layer does.
- Avoid scheduling automated operations (sync/export/leases) on notebooks known to be locked; query lock state beforehand.
- If the notebook should already be unlocked, verify no re-lock happened (timeout/manual) between unlock and the call.
Example fix
// before
boxID, err := model.AcquireEncryptedBoxOperation(id)
if err != nil { return err }
// after
boxID, err := model.AcquireEncryptedBoxOperation(id)
if err != nil {
if errors.Is(err, model.ErrEncryptedBoxNotUnlocked) {
return toolErrorResult("encrypted notebook is locked, please unlock it first")
}
return err
} Defensive patterns
Strategy: try-catch
Validate before calling
// Check unlock state before acquiring leases
if !model.IsEncryptedBoxUnlocked(boxID) {
return errors.New("unlock the notebook before running this tool")
} Try / catch
if err := model.AcquireEncryptedBoxOperation(boxID); err != nil {
if errors.Is(err, model.ErrEncryptedBoxNotUnlocked) {
return toolErrorResult("encrypted notebook is locked, please unlock it first")
}
return err
} Prevention
- Unlock encrypted notebooks at the start of any batch/scripted operation.
- Be aware of auto-relock timeouts; re-check state before long-running jobs.
- Surface the sentinel error to users as an 'unlock first' prompt instead of a generic failure.
When it happens
Trigger: Calling AcquireEncryptedBoxOperation / AcquireEncryptedBoxOperations (e.g. from MCP server.go:284 tool handlers) while the notebook is locked or during a lifecycle transition where acceptOperations is false.
Common situations: Running an MCP tool against an encrypted notebook that has not been unlocked since kernel start; the notebook was re-locked by idle timeout or manually; concurrent lock operation rejected leases.
Related errors
- encrypted notebook is locked, please unlock it first
- encrypted notebook operation scope is closed
- master password migration is pending
- 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/61937e1d1667283a.
Report an issue: GitHub.