siyuan-note/siyuan · warning

Conf.Language(323)

Error message

Conf.Language(323)

What it means

DisableEncryptedNotebook refuses to disable the encrypted-notebook feature when the history directory still contains snapshots of deleted encrypted notebooks (Conf.Language(323)). Those snapshots can only be recovered with the current MasterSalt/KEKVerifier, so wiping the key material first would make the history unrecoverable. The kernel deliberately aborts and asks the user to clear that history first.

Source

Thrown at kernel/model/crypto.go:1108

	notebookCryptoMu.Lock()
	defer notebookCryptoMu.Unlock()

	// 检查是否还有加密笔记本(含 conf 损坏但存在备份的)
	ids, listErr := listAllEncryptedBoxIDs()
	if listErr != nil {
		return fmt.Errorf("list encrypted notebooks failed: %w", listErr)
	}
	if len(ids) > 0 {
		return errors.New("cannot disable encrypted notebook feature while encrypted notebooks exist, remove them first")
	}
	// 检查历史目录中是否存在已删除加密笔记本的历史快照:其恢复仍依赖当前 MasterSalt/KEKVerifier,
	// 删除备份前必须先清除这些历史(详见设计 §19)
	hasHistory, historyErr := scanEncryptedNotebookHistory()
	if historyErr != nil {
		return fmt.Errorf("check encrypted notebook history failed: %w", historyErr)
	}
	if hasHistory {
		return errors.New(Conf.Language(323))
	}

	Conf.m.Lock()
	Conf.NotebookCrypto.Enabled = false
	Conf.NotebookCrypto.MasterSalt = nil
	Conf.NotebookCrypto.KEKVerifier = nil
	Conf.NotebookCrypto.VerifierNonce = nil
	Conf.m.Unlock()

	Conf.Save()
	removeNotebookCryptoBackup() // 禁用时清理备份,避免残留旧密钥材料
	IncSync()
	return nil
}

// restoreNotebookCryptoConfigFromBackup 把备份里的 NotebookCrypto 配置装回本机 conf.json(不需主密码)。
// 用于数据同步/导入 Data.zip 后:备份文件随 DataDir 到达新设备,但本机 conf.json 的 NotebookCrypto 还是空的。
// 此时把 salt/verifier/KDFParams 装回并置 Enabled=true,让 UI 显示"已启用",笔记本显示为锁定(解锁仍需主密码)。

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Open the history panel and permanently clear the remaining encrypted-notebook history snapshots (Data > history), then retry disabling the feature
  2. Manually remove the orphaned encrypted-notebook snapshots from the workspace history directory, then call the API again
  3. If the history is still needed, do not disable the feature; decrypt/export the notebooks first, clear history, then disable
Defensive patterns

Strategy: validation

Validate before calling

// Go (kernel client script): refuse to disable while encrypted-notebook history remains
if has, _ := model.ScanEncryptedNotebookHistoryForCheck(); has {
    return errors.New("clear encrypted-notebook history snapshots before disabling the feature")
}
_ = model.DisableEncryptedNotebook()

Prevention

When it happens

Trigger: Calling POST /api/notebook/disableEncryptedNotebooks (kernel handler disableEncryptedNotebooks -> DisableEncryptedNotebook) while scanEncryptedNotebookHistory() finds history snapshots belonging to previously deleted encrypted notebooks.

Common situations: A user deleted encrypted notebooks in the past (leaving stale entries under the history directory), then tries to switch the encrypted-notebook feature off from settings; or after restoring/syncing data that still carries old encrypted-notebook history.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/3dce0f16fb0b6d37. Report an issue: GitHub.