siyuan-note/siyuan · critical · errMasterPasswordMigrationPending
master password migration is pending: Master password change
Error message
master password migration is pending: Master password change partially failed. Please restart SiYuan to complete recovery. Detail: %s: rebuild encrypted conf from migration entry failed: %s
What it means
Returned by ChangeMasterPassword Phase 3 (crypto.go:1786-1802) when both the notebook conf.json and the per-notebook backup are unavailable, so the code rebuilds BoxCrypt directly from the migration manifest entry (the authoritative source of the new key material) - and that rebuild's box.SaveConf still fails. The migration manifest is preserved; restart completes recovery.
Source
Thrown at kernel/model/crypto.go:1800
if saveErr := box.SaveConf(boxConf); saveErr != nil {
return fmt.Errorf("%w: %s", errMasterPasswordMigrationPending,
fmt.Sprintf(Conf.Language(320), entry.BoxID+": rebuild encrypted conf from backup failed: "+saveErr.Error()))
}
} else {
// conf 与 backup 均不可用:manifest 是该 box 加密密钥的权威来源,直接从 entry 重建 BoxCrypt,
// 避免改密因瞬时 conf 损坏而中断(详见 recoverMasterPasswordMigration 中的对称处理)。
logging.LogWarnf("rebuild encrypted box [%s] from migration entry (conf and backup both unavailable)", entry.BoxID)
boxConf = box.GetConf()
boxConf.Encrypted = true
boxConf.BoxCrypt = &conf.BoxEncryption{
WrappedDEK: entry.NewWrappedDEK,
WrapNonce: entry.NewWrapNonce,
Spec: entry.NewSpec,
Metadata: entry.Metadata,
CreatedAt: time.Now().UnixMilli(),
}
if saveErr := box.SaveConf(boxConf); saveErr != nil {
return fmt.Errorf("%w: %s", errMasterPasswordMigrationPending,
fmt.Sprintf(Conf.Language(320), entry.BoxID+": rebuild encrypted conf from migration entry failed: "+saveErr.Error()))
}
}
}
boxConf.BoxCrypt.WrappedDEK = entry.NewWrappedDEK
boxConf.BoxCrypt.Spec = entry.NewSpec
boxConf.BoxCrypt.WrapNonce = entry.NewWrapNonce
boxConf.BoxCrypt.Metadata = append([]byte(nil), entry.Metadata...)
if err = box.SaveConf(boxConf); err != nil {
return fmt.Errorf("%w: %s", errMasterPasswordMigrationPending,
fmt.Sprintf(Conf.Language(320), entry.BoxID+": save conf failed: "+err.Error()))
}
if err = writeNotebookCryptBackup(entry.BoxID, boxConf.BoxCrypt); err != nil {
return fmt.Errorf("%w: %s", errMasterPasswordMigrationPending,
fmt.Sprintf(Conf.Language(320), entry.BoxID+": update notebook crypt backup failed: "+err.Error()))
}
}
View on GitHub (pinned to afa823b6b4)
Solutions
- Repair write access to <data>/<boxID>/.siyuan/ (space, permissions, locks) for the box named in the detail
- Restart SiYuan so migration recovery replays the manifest and retries the rebuild, then log in with the new password
- After recovery, verify the affected notebook unlocks and re-exports/backups its key material (a fresh crypt backup is written on next successful unlock)
Defensive patterns
Strategy: type-guard
Type guard
func isMigrationPendingErr(err error) bool {
return errors.Is(err, errMasterPasswordMigrationPending) // in-package; outside use string prefix check
} Try / catch
if err := model.ChangeMasterPassword(oldPw, newPw); isMigrationPendingErr(err) {
logMigrationDetail(err) // names the box whose conf+backup rebuild failed
instructUserRestart() // recovery replays the manifest entry for that box
return
} Prevention
- Keep per-notebook crypt backups intact - they are the first rebuild source when conf is damaged
- Repair notebooks with missing/corrupt conf AND backup before rotating the master password
- Maintain writability of <data>/<boxID>/.siyuan/ for every encrypted notebook during the change
When it happens
Trigger: A notebook whose conf.json is corrupt/unwritable and whose backup is missing/damaged, combined with a write failure (disk full, permissions, file lock) when saving the reconstructed conf.json during the password change.
Common situations: Notebooks already in a degraded state (deleted backup file plus damaged conf) hit during password rotation; failing disk; workspace permission changes made between sessions.
Related errors
- master password migration is pending: Master password change
- master password migration is pending: Master password change
- master password migration is pending: %v
- master password migration is pending: Master password change
- master password migration is pending: Master password change
AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18).
Data as JSON: /api/errors/97489e6ef8ab7cae.
Report an issue: GitHub.