{"record":{"id":"31f31610a7d81cc9","repo":"siyuan-note/siyuan","slug":"notebook-s-has-conflicting-normal-and-encrypted","errorCode":null,"errorMessage":"notebook [%s] has conflicting normal and encrypted identities","messagePattern":"notebook \\[(.+?)\\] has conflicting normal and encrypted identities","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"kernel/model/import.go","lineNumber":1363,"sourceCode":"\t\tif filelock.IsExist(backupPath) {\n\t\t\tbackup, err = readBoxEncryptionFile(backupPath)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid imported notebook identity [%s]: %w\", boxID, err)\n\t\t\t}\n\t\t}\n\n\t\tvar boxCrypt *conf.BoxEncryption\n\t\tif boxConf != nil && boxConf.Encrypted {\n\t\t\tif boxConf.BoxCrypt != nil && validateBoxEncryption(boxConf.BoxCrypt) == nil {\n\t\t\t\tboxCrypt = boxConf.BoxCrypt\n\t\t\t} else {\n\t\t\t\tboxCrypt = backup\n\t\t\t}\n\t\t\tif boxCrypt == nil {\n\t\t\t\treturn nil, fmt.Errorf(\"encrypted notebook [%s] has no valid identity\", boxID)\n\t\t\t}\n\t\t} else if boxConf != nil && backup != nil {\n\t\t\treturn nil, fmt.Errorf(\"notebook [%s] has conflicting normal and encrypted identities\", boxID)\n\t\t} else if backup != nil {\n\t\t\tboxCrypt = backup\n\t\t}\n\n\t\tpayloadFound, payloadErr := hasEncryptedNotebookPayloadAtPath(boxDir)\n\t\tif payloadErr != nil {\n\t\t\treturn nil, fmt.Errorf(\"inspect imported notebook [%s] failed: %w\", boxID, payloadErr)\n\t\t}\n\t\tif boxCrypt == nil && payloadFound {\n\t\t\treturn nil, fmt.Errorf(\"imported notebook [%s] contains encrypted payload without identity\", boxID)\n\t\t}\n\t\tif boxCrypt == nil {\n\t\t\tcontinue\n\t\t}\n\n\t\tif err = validateBoxEncryption(boxCrypt); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid imported notebook identity [%s]: %w\", boxID, err)\n\t\t}","sourceCodeStart":1345,"sourceCodeEnd":1381,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/import.go#L1345-L1381","documentation":"Identity must be unambiguous: if conf.json does NOT declare the notebook encrypted but an encryption backup file exists (or vice versa), validateImportedNotebookIdentities returns 'notebook [%s] has conflicting normal and encrypted identities'. Such a mix could let plaintext content silently overwrite or masquerade as encrypted content, so the import is rejected until the identity is resolved.","triggerScenarios":"ImportData importing a notebook where .siyuan/conf.json has encrypted=false (or absent) while .siyuan/<notebookCryptoBackupFilename> also exists — typically from mixing plaintext and encrypted exports of the same notebook, or a partially completed encryption migration in the source workspace.","commonSituations":"1) Merging a pre-encryption export with post-encryption .siyuan metadata. 2) Interrupted encryption migration in the source workspace leaving both states on disk. 3) Hand-editing conf.json's encrypted flag. 4) Combining notebooks from two workspaces with different encryption settings.","solutions":["Determine the notebook's true state in the source workspace; re-export a clean, consistent copy (fully encrypted or fully plaintext) and re-import.","If the notebook is genuinely encrypted, fix conf.json to encrypted=true with its BoxCrypt material intact so identity is unambiguous.","If the backup file is a stale leftover from an aborted migration, remove it only after confirming the notebook is truly plaintext and keys are not needed — keep recovery material otherwise.","Import the two conflicting copies into separate notebooks rather than merging them into one."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const conf = JSON.parse(await fs.promises.readFile(path.join(boxDir, '.siyuan', 'conf.json'), 'utf8'));\nconst hasBackup = fs.existsSync(path.join(boxDir, '.siyuan', notebookCryptoBackupFilename));\nif (!conf.encrypted && hasBackup) {\n  throw new Error('conflicting identities: plaintext conf with encryption backup present');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await importData(src);\n} catch (e) {\n  if (/conflicting normal and encrypted identities/.test(e.msg)) {\n    console.error('Re-export a consistent copy of the notebook (fully encrypted or fully plaintext) and retry');\n  }\n  throw e;\n}","preventionTips":["Never mix pre-encryption exports with post-encryption .siyuan metadata","Complete encryption migrations in the source workspace before exporting","Do not manually toggle the encrypted flag in conf.json"],"tags":["encryption","conflict","identity","import","siyuan"],"backgroundTag":"conflicting-config-options","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}