siyuan-note/siyuan · error

encrypted notebook is locked, please unlock it first

Error message

encrypted notebook is locked, please unlock it first

What it means

`beginBlockToolScope` detected that the target `notebook` is encrypted and is currently locked (no unlocked session). MCP block tools refuse to read or mutate an encrypted notebook until the user unlocks it, so they release the read lock and abort.

Source

Thrown at kernel/mcp/tools/block.go:616

			sb.WriteString(fmt.Sprintf("--- %s ---\n%s\n\n", id, kd))
		} else {
			sb.WriteString(fmt.Sprintf("--- %s ---\n(not found)\n\n", id))
		}
	}

	return CallToolResult{Content: []ContentItem{{Type: "text", Text: sb.String()}}}, nil
}

func beginBlockToolScope(args map[string]any, mutation bool, ids ...string) (boxID string, release func(), err error) {
	release = func() {}
	notebook, _ := args["notebook"].(string)
	notebook = strings.TrimSpace(notebook)
	encrypted := notebook != "" && model.IsEncryptedBox(notebook)
	if encrypted {
		model.HoldBoxReadLock(notebook)
		if !model.IsBoxUnlocked(notebook) {
			model.ReleaseBoxReadLock(notebook)
			return "", release, fmt.Errorf("encrypted notebook is locked, please unlock it first")
		}
		release = func() {
			model.ReleaseBoxReadLock(notebook)
		}
		boxID = notebook
	}

	fail := func(format string, values ...any) (string, func(), error) {
		release()
		return "", func() {}, fmt.Errorf(format, values...)
	}
	for _, id := range ids {
		if id == "" {
			continue
		}
		queryBoxID := ""
		if encrypted {
			queryBoxID = notebook

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Unlock the encrypted notebook in the SiYuan UI (Settings or the notebook context menu) before retrying the tool call.
  2. Confirm the `notebook` argument is the correct encrypted box ID and that the unlock succeeded.
  3. If the call should target a non-encrypted box, correct the `notebook` argument.
Defensive patterns

Strategy: validation

Validate before calling

// Check encryption + unlock state before invoking a block tool.
if notebook != "" && model.IsEncryptedBox(notebook) && !model.IsBoxUnlocked(notebook) {
    return errors.New("unlock the encrypted notebook before calling this tool")
}

Prevention

When it happens

Trigger: Invoking any block tool with a `notebook` argument whose `model.IsEncryptedBox` is true while `model.IsBoxUnlocked` returns false — i.e. the box is encrypted and the user has not supplied the unlock passphrase in this session.

Common situations: After a kernel restart the encrypted notebook is locked again and a tool call is made before the user unlocks it via the UI. The `notebook` argument points at an encrypted box the user forgot to unlock.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/94779857dc84d39e. Report an issue: GitHub.