{"record":{"id":"de0a067d744c49b8","repo":"siyuan-note/siyuan","slug":"write-notebook-crypt-backup-failed-w","errorCode":null,"errorMessage":"write notebook crypt backup failed: %w","messagePattern":"write notebook crypt backup failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/crypto.go","lineNumber":2583,"sourceCode":"\t}()\n\n\tenc, dek, err := WrapNewDEK(id, kek)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tbox := &Box{ID: id}\n\tboxConf := box.GetConf()\n\tboxConf.Encrypted = true\n\tboxConf.BoxCrypt = enc\n\tif err = encryptBoxMetadata(id, boxConf, dek); err != nil {\n\t\treturn \"\", fmt.Errorf(\"encrypt notebook metadata failed: %w\", err)\n\t}\n\tif err = box.SaveConf(boxConf); err != nil {\n\t\treturn \"\", fmt.Errorf(\"save encrypted notebook conf failed: %w\", err)\n\t}\n\tif err = writeNotebookCryptBackup(id, enc); err != nil {\n\t\treturn \"\", fmt.Errorf(\"write notebook crypt backup failed: %w\", err)\n\t}\n\t// 回读校验加密配置已落盘，避免写失败后按普通笔记本处理\n\tverifyConf := box.GetConf()\n\tif verifyConf == nil || !verifyConf.Encrypted || verifyConf.BoxCrypt == nil {\n\t\terr = errors.New(\"encrypted notebook metadata verification failed after write\")\n\t\treturn \"\", err\n\t}\n\tmarkRuntimeEncryptedBox(id)\n\tinvalidateEncryptedPublishAccessCache()\n\n\t// 复用刚派生的 DEK 直接开 db + 缓存，省去再次 Argon2id 解锁\n\tcachedDEKsLock.Lock()\n\tif err = sql.OpenEncryptedDB(id, dek); err != nil {\n\t\tcachedDEKsLock.Unlock()\n\t\treturn \"\", err\n\t}\n\tif err = treenode.OpenEncryptedBlockTreeDB(id, dek); err != nil {\n\t\tsql.CloseEncryptedDB(id)","sourceCodeStart":2565,"sourceCodeEnd":2601,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/crypto.go#L2565-L2601","documentation":"Returned by CreateEncryptedBox when writeNotebookCryptBackup fails to write the recovery backup of the wrapped DEK (BoxCrypt blob). The %w wraps the I/O error. This backup is critical for recovery if the main .syconf is lost; failure triggers cleanup of the half-created notebook.","triggerScenarios":"writeNotebookCryptBackup encounters a disk I/O error writing the backup file (separate from the main notebook conf). Same causes as SaveConf failure: disk full, permissions, read-only FS.","commonSituations":"The backup path is on a different volume or subdirectory that has different permissions. Disk ran out of space between writing .syconf and writing the backup. File-lock contention on the backup location.","solutions":["Check disk space and permissions on the backup directory (typically under the workspace's crypto backup path).","Ensure no other process holds a lock on the backup file location.","Retry CreateEncryptedBox after resolving the I/O issue — the deferred cleanup will have removed the failed attempt."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"id, err := model.CreateEncryptedBox(name, password)\nif err != nil {\n    if strings.Contains(err.Error(), \"write notebook crypt backup failed\") {\n        // backup path I/O issue — check backup directory permissions/space\n    }\n    return err\n}","preventionTips":["Ensure the backup directory (for the crypt recovery file) is writable and has adequate space.","Don't place the workspace on a read-only or nearly-full volume.","Verify file-lock software isn't blocking writes to the backup location."],"tags":["encryption","notebook-creation","disk-io","backup","crypto"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}