siyuan-note/siyuan · critical
notebook [ ] has conflicting normal and encrypted identities
Error message
notebook [%s] has conflicting normal and encrypted identities
What it means
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.
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.
Defensive patterns
Strategy: validation
Validate before calling
const conf = JSON.parse(await fs.promises.readFile(path.join(boxDir, '.siyuan', 'conf.json'), 'utf8'));
const hasBackup = fs.existsSync(path.join(boxDir, '.siyuan', notebookCryptoBackupFilename));
if (!conf.encrypted && hasBackup) {
throw new Error('conflicting identities: plaintext conf with encryption backup present');
} Try / catch
try {
await importData(src);
} catch (e) {
if (/conflicting normal and encrypted identities/.test(e.msg)) {
console.error('Re-export a consistent copy of the notebook (fully encrypted or fully plaintext) and retry');
}
throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- encrypted notebook [ ] has no valid identity
- invalid imported notebook identity
- Conf.Language(388) with escaped relative path…
- refuse to overwrite existing encrypted notebook
- 199
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/31f31610a7d81cc9.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/import.go:1363
if filelock.IsExist(backupPath) {
backup, err = readBoxEncryptionFile(backupPath)
if err != nil {
return nil, fmt.Errorf("invalid imported notebook identity [%s]: %w", boxID, err)
}
}
var boxCrypt *conf.BoxEncryption
if boxConf != nil && boxConf.Encrypted {
if boxConf.BoxCrypt != nil && validateBoxEncryption(boxConf.BoxCrypt) == nil {
boxCrypt = boxConf.BoxCrypt
} else {
boxCrypt = backup
}
if boxCrypt == nil {
return nil, fmt.Errorf("encrypted notebook [%s] has no valid identity", boxID)
}
} else if boxConf != nil && backup != nil {
return nil, fmt.Errorf("notebook [%s] has conflicting normal and encrypted identities", boxID)
} else if backup != nil {
boxCrypt = backup
}
payloadFound, payloadErr := hasEncryptedNotebookPayloadAtPath(boxDir)
if payloadErr != nil {
return nil, fmt.Errorf("inspect imported notebook [%s] failed: %w", boxID, payloadErr)
}
if boxCrypt == nil && payloadFound {
return nil, fmt.Errorf("imported notebook [%s] contains encrypted payload without identity", boxID)
}
if boxCrypt == nil {
continue
}
if err = validateBoxEncryption(boxCrypt); err != nil {
return nil, fmt.Errorf("invalid imported notebook identity [%s]: %w", boxID, err)
}View on GitHub (pinned to 9f775e8a12)