siyuan-note/siyuan · critical
master password migration is pending
Error message
master password migration is pending
What it means
errMasterPasswordMigrationPending is a sentinel marking an unfinished master-password change: the global verifier was already switched to the new KEK, but some per-notebook WrappedDEK material or the global backup has not been fully persisted (crash mid-migration, or a per-box conf/backup save failing in ChangeMasterPassword phases 3-4). It is returned bare when recovery still cannot verify all boxes against the new KEK, and wrapped with box-level detail (%w) when re-writing a box conf, per-notebook backup, or the global backup fails during recovery/continuation.
Source
Thrown at kernel/model/crypto.go:166
})
if errors.Is(err, errEncryptedNotebookPayloadFound) {
return true, nil
}
return false, err
}
const encryptedAssetMetadataMaxSize = 1024 * 1024
const encryptedAssetChunkSize = 1024 * 1024
const encryptedAssetChunkMaxCiphertextSize = encryptedAssetChunkSize + 1024
type encryptedAssetMetadata struct {
OriginalName string `json:"originalName"`
Size int64 `json:"size"`
Chunks uint64 `json:"chunks"`
}
// errMasterPasswordMigrationPending 表示改密已切换全局 verifier,但部分笔记本配置尚待恢复。
var errMasterPasswordMigrationPending = errors.New("master password migration is pending")
// notebookCryptoMu 串行化加密笔记本的控制面操作(Enable/Disable/Create/ChangeMasterPassword/Import/restore 等),
// 避免 ChangeMasterPassword 枚举与 CreateEncryptedBox 并发导致新笔记本用旧 KEK 但 verifier 已切换的不可恢复状态。
var notebookCryptoMu sync.Mutex
var masterPasswordMigrationMu sync.Mutex
// boxLifecycleLocks 为每个 box 提供一个 RWMutex,协调锁定操作与在途解密请求。
// 在途解密请求持读锁,LockBox 持写锁,确保锁定后不会有新的解密输出。
var boxLifecycleLocks = sync.Map{} // map[string]*sync.RWMutex
func acquireBoxReadLock(boxID string) {
muI, _ := boxLifecycleLocks.LoadOrStore(boxID, &sync.RWMutex{})
muI.(*sync.RWMutex).RLock()
}
func releaseBoxReadLock(boxID string) {
if muI, ok := boxLifecycleLocks.Load(boxID); ok {View on GitHub (pinned to afa823b6b4)
Solutions
- Unlock/verify again with the NEW master password - the recovery path (recoverMasterPasswordMigration) re-runs and completes the pending writes
- Make sure the workspace disk is writable and no second kernel instance or sync tool is touching conf files, then retry
- Do not attempt the old password - the global verifier has already switched, which is exactly what this sentinel reports
- Once unlocked, export the key backup (ExportNotebookCryptoBackup) so a future interruption is recoverable offline
Defensive patterns
Strategy: try-catch
Try / catch
err := model.CheckMasterPassword(password) // or the unlock flow
if err != nil {
if strings.Contains(err.Error(), "master password migration is pending") {
// interrupted change-password: retry with the NEW password until recovery completes; never fall back to the old one
}
} Prevention
- Never force-quit the kernel while a master password change is in progress
- Run only one kernel instance per workspace so migration manifest writes do not race
- Keep the workspace disk writable; conf/backup write failures are the main non-crash trigger
- Export the key backup right after enabling or changing the master password
When it happens
Trigger: kernel killed or crashed between writeMasterPasswordMigration and removeMasterPasswordMigration; disk full or filelock contention while ChangeMasterPassword rewrites box confs; then the next unlock with the new password fails verifyKEKAgainstExistingBoxes or saveNotebookCryptoBackup and returns this sentinel (kernel/model/crypto.go:1279,1283,1783-1821).
Common situations: Force-quitting the app during a master password change; workspace on a flaky/synced drive where conf writes fail; two operations racing (the code serializes via notebookCryptoMu/masterPasswordMigrationMu, but external processes bypass that).
Related errors
- Conf.Language(315)
- Conf.Language(324)
- master password migration is pending: %v
- attribute view spec is too new
- encrypted notebook is locked, please unlock it first
AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18).
Data as JSON: /api/errors/7573baf35a1bb26c.
Report an issue: GitHub.