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

  1. Determine the notebook's true state in the source workspace; re-export a clean, consistent copy (fully encrypted or fully plaintext) and re-import.
  2. If the notebook is genuinely encrypted, fix conf.json to encrypted=true with its BoxCrypt material intact so identity is unambiguous.
  3. 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.
  4. 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

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


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)