{"record":{"id":"04ed48bfcee3beab","repo":"siyuan-note/siyuan","slug":"encrypted-notebook-metadata-verification-failed-af","errorCode":null,"errorMessage":"encrypted notebook metadata verification failed after write","messagePattern":"encrypted notebook metadata verification failed after write","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"kernel/model/crypto.go","lineNumber":2588,"sourceCode":"\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)\n\t\tcachedDEKsLock.Unlock()\n\t\treturn \"\", err\n\t}\n\tcachedDEKs[id] = dek\n\tcachedDEKsLock.Unlock()","sourceCodeStart":2570,"sourceCodeEnd":2606,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/crypto.go#L2570-L2606","documentation":"Returned by CreateEncryptedBox when, after SaveConf and writeNotebookCryptBackup both report success, a readback (box.GetConf) shows the encrypted configuration is NOT actually persisted — Encrypted is false or BoxCrypt is nil. This is a data-integrity safety net: it prevents a notebook from being treated as plain when it should be encrypted (which would cause plaintext writes to what is meant to be an encrypted store).","triggerScenarios":"SaveConf reported success but the file wasn't actually written or was overwritten by another process between write and readback. A race with a concurrent conf writer, a stale file-cache, or a filesystem that acknowledged a write before flushing.","commonSituations":"Concurrent operations modifying the same notebook's .syconf. Filesystem caching layer that delays persistence. Another kernel instance writing to the same workspace (unsupported but happens in misconfigured setups).","solutions":["Ensure only one kernel instance is running against the workspace.","Check for concurrent code paths that write to the same notebook's .syconf and serialize them with notebookCryptoMu or a per-box lock.","Examine filesystem sync semantics — if using a network FS, ensure writes are fsync'd before the readback."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":"id, err := model.CreateEncryptedBox(name, password)\nif err != nil {\n    if strings.Contains(err.Error(), \"verification failed after write\") {\n        // integrity violation — possible concurrent writer or FS caching issue\n        logging.LogErrorf(\"critical: encrypted conf did not persist for box %s\", id)\n    }\n    return err\n}","preventionTips":["Never run two kernel instances against the same workspace.","Serialize all .syconf writers with notebookCryptoMu or a per-box lock.","On network filesystems, ensure fsync semantics so readback reflects the write."],"tags":["encryption","notebook-creation","data-integrity","verification","crypto"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}