{"record":{"id":"f3d683e683dd3eec","repo":"siyuan-note/siyuan","slug":"please-unlock-the-encrypted-notebook-first-f3d683","errorCode":null,"errorMessage":"Please unlock the encrypted notebook first","messagePattern":"Please unlock the encrypted notebook first","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/import.go","lineNumber":1045,"sourceCode":"\t\tif err = filelock.Copy(assetsDir, dataAssets); err != nil {\n\t\t\tlogging.LogErrorf(\"copy assets from [%s] to [%s] failed: %s\", assetsDir, dataAssets, err)\n\t\t\treturn nil, err\n\t\t}\n\t\tif removeErr := os.RemoveAll(assetsDir); removeErr != nil {\n\t\t\treturn nil, removeErr\n\t\t}\n\t}\n\treturn assetPathMap, nil\n}\n\nfunc writeImportedTree(boxID, syPath, newSyPath, relPath string, data []byte) error {\n\tif IsEncryptedBox(boxID) {\n\t\tHoldBoxReadLock(boxID)\n\t\tdefer ReleaseBoxReadLock(boxID)\n\n\t\tdek, err := GetDEKIfUnlocked(boxID)\n\t\tif err != nil {\n\t\t\treturn errors.New(Conf.Language(314))\n\t\t}\n\t\tdata, err = EncryptFile(boxID, relPath, dek, data)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tif err := os.WriteFile(syPath, data, 0644); err != nil {\n\t\treturn err\n\t}\n\treturn filelock.Rename(syPath, newSyPath)\n}\n\nfunc validateImportedNotebookIdentities(tmpDataPath string) ([]string, error) {\n\tdirs, err := os.ReadDir(tmpDataPath)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n","sourceCodeStart":1027,"sourceCodeEnd":1063,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/afa823b6b4e4f183511e0bc0a3be93caa94c7c97/kernel/model/import.go#L1027-L1063","documentation":"writeImportedTree encrypts each rewritten .sy when the target box is encrypted; it calls GetDEKIfUnlocked, which fails when the notebook is locked (no data-encryption key cached in memory - after restart, auto-lock, or LockBox). Rather than writing plaintext into an encrypted notebook, the import is refused with Language(314) 'Please unlock the encrypted notebook first'.","triggerScenarios":"importSY / importSYAuto / continueImportSY into an encrypted notebook that has not been unlocked in this kernel session. The failure surfaces per-document during the write-back loop (kernel/model/import.go:670 -> 1045).","commonSituations":"Importing right after an app restart before unlocking the notebook. Headless/API automation that never performs the unlock step. Auto-lock policy locking the box between starting and finishing a long import.","solutions":["Unlock the encrypted notebook in the UI (enter its passphrase), then re-run the import","For automation, perform the unlock flow via API before calling import endpoints","Alternatively import into a non-encrypted notebook first, then encrypt/migrate afterwards"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if model.IsEncryptedBox(boxID) {\n    if _, err := model.GetDEKIfUnlocked(boxID); err != nil {\n        // notebook is locked: prompt for passphrase / unlock via API before importing\n        return err\n    }\n}\nerr := model.ImportSY(zipPath, boxID, toPath)","typeGuard":"func isLockedNotebookErr(err error) bool {\n    return err != nil && err.Error() == model.Conf.Language(314)\n}","tryCatchPattern":"if err := model.ImportSY(zipPath, boxID, toPath); err != nil {\n    if err.Error() == model.Conf.Language(314) {\n        // unlock the notebook, then retry the import once\n    }\n}","preventionTips":["Unlock encrypted notebooks before starting any import into them","In automation, unlock first and re-check GetDEKIfUnlocked right before long imports (auto-lock may strike mid-run)","Consider importing into a plain notebook and encrypting afterwards for unattended jobs"],"tags":["siyuan","import","encrypted-notebook","locked","dek"],"backgroundTag":"encrypted-notebook-locked","analyzedSha":"afa823b6b4e4f183511e0bc0a3be93caa94c7c97","analyzedAt":"2026-08-18T17:04:10.865Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}