siyuan-note/siyuan · error
notebook [%s] has conflicting normal and encrypted identitie
Error message
notebook [%s] has conflicting normal and encrypted identities
What it means
Thrown by validateImportedNotebookIdentities when the conf.json explicitly marks the notebook as NOT encrypted (Encrypted: false or absent), but a backup encryption file (notebookCryptoBackupFilename) exists in .siyuan/. This is a contradictory state: the notebook claims to be a normal notebook, yet it carries encrypted-notebook identity artifacts. The import is refused to prevent silently treating encrypted data as plaintext or vice versa.
Source
Thrown at kernel/model/import.go:1080
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 251596fc0d)
Solutions
- If the notebook is genuinely not encrypted, remove the .siyuan/<backup-filename> from the Data.zip before importing.
- If the notebook IS encrypted, fix the conf.json to set Encrypted: true and ensure BoxCrypt is populated.
- Re-export from the source SiYuan to get a consistent state.
- Manually reconcile the conf.json and backup file to agree on encryption status before importing.
Defensive patterns
Strategy: validation
Validate before calling
// Check for identity conflicts before importing
func checkIdentityConflict(tmpDataPath, boxID string) error {
confPath := filepath.Join(tmpDataPath, boxID, ".siyuan", "conf.json")
backupPath := filepath.Join(tmpDataPath, boxID, ".siyuan", notebookCryptoBackupFilename)
if !filelock.IsExist(confPath) || !filelock.IsExist(backupPath) {
return nil
}
data, _ := filelock.ReadFile(confPath)
boxConf := conf.NewBoxConf()
if err := gulu.JSON.UnmarshalJSON(data, boxConf); err != nil {
return err
}
if !boxConf.Encrypted {
return fmt.Errorf("notebook %s: conf says not encrypted but backup exists — conflict", boxID)
}
return nil
} Try / catch
encryptedBoxIDs, err := validateImportedNotebookIdentities(tmpDataPath)
if err != nil {
if strings.Contains(err.Error(), "conflicting normal and encrypted identities") {
// Suggest removing the backup file or fixing conf.json
boxID := extractBoxID(err.Error())
backupPath := filepath.Join(tmpDataPath, boxID, ".siyuan", notebookCryptoBackupFilename)
if !model.IsEncryptedBox(boxID) {
os.Remove(backupPath) // remove stale backup
}
}
} Prevention
- Re-export Data.zip to ensure consistent encryption state.
- Do not manually toggle the Encrypted field in conf.json without also updating/removing the backup file.
- If a notebook was decrypted, ensure the export process cleans up backup files.
- Inspect the archive's .siyuan/ directory for consistency before importing.
When it happens
Trigger: Calling validateImportedNotebookIdentities where boxConf exists with Encrypted == false, AND backup != nil (backup file exists and was successfully read). The check is at import.go:1079-1080.
Common situations: Manual editing of conf.json to remove the Encrypted flag while leaving the backup file. A notebook that was decrypted but the backup file was not cleaned up. Version migration that changed how encryption state is tracked. Export from a SiYuan version that handled encryption state differently.
Related errors
- invalid imported notebook identity [%s]: %w
- encrypted notebook [%s] has no valid identity
- read imported notebook conf [%s] failed: %w
- parse imported notebook conf [%s] failed: %w
- inspect imported notebook [%s] failed: %w
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/31f31610a7d81cc9.
Report an issue: GitHub.