siyuan-note/siyuan · error
encrypted notebook [%s] has no valid identity
Error message
encrypted notebook [%s] has no valid identity
What it means
Thrown by validateImportedNotebookIdentities when the conf.json marks the notebook as encrypted (Encrypted: true) but no valid encryption identity can be found. The kernel first tries BoxCrypt from conf.json (if it passes validateBoxEncryption), then falls back to the backup file. If both are nil or invalid, the notebook has no way to unwrap its DEK, making its content permanently inaccessible. The import is refused to avoid importing unrecoverable data.
Source
Thrown at kernel/model/import.go:1077
}
var backup *conf.BoxEncryption
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
}
View on GitHub (pinned to 251596fc0d)
Solutions
- Re-export the Data.zip ensuring the .siyuan/ directory with encryption identity files is included.
- Verify the source SiYuan version matches the target version (encryption identity format must be compatible).
- If the source notebook is truly encrypted but identity is lost, the data is unrecoverable — re-export from a backup that includes the identity.
- If encryption was never intended, edit the conf.json in the Data.zip to set Encrypted to false before importing.
Defensive patterns
Strategy: validation
Validate before calling
// Check that encrypted notebooks in the archive have encryption identity
func checkEncryptedNotebookIdentity(tmpDataPath, boxID string) error {
confPath := filepath.Join(tmpDataPath, boxID, ".siyuan", "conf.json")
backupPath := filepath.Join(tmpDataPath, boxID, ".siyuan", notebookCryptoBackupFilename)
if !filelock.IsExist(confPath) {
return nil
}
data, _ := filelock.ReadFile(confPath)
boxConf := conf.NewBoxConf()
if err := gulu.JSON.UnmarshalJSON(data, boxConf); err != nil {
return err
}
if !boxConf.Encrypted {
return nil
}
if boxConf.BoxCrypt != nil && validateBoxEncryption(boxConf.BoxCrypt) == nil {
return nil
}
if !filelock.IsExist(backupPath) {
return fmt.Errorf("encrypted notebook %s has no identity and no backup", boxID)
}
return nil
} Try / catch
encryptedBoxIDs, err := validateImportedNotebookIdentities(tmpDataPath)
if err != nil {
if strings.Contains(err.Error(), "has no valid identity") {
// Cannot recover — data would be inaccessible
return fmt.Errorf("encrypted notebook identity is missing; re-export with .siyuan/ directory")
}
} Prevention
- Always include the complete .siyuan/ directory when exporting encrypted notebooks.
- Verify the archive contains both conf.json and the encryption backup file for encrypted notebooks.
- Do not strip hidden directories from the Data.zip.
- Re-export from the source SiYuan if identity files are missing.
When it happens
Trigger: Calling validateImportedNotebookIdentities where boxConf.Encrypted is true, but both boxConf.BoxCrypt is nil-or-invalid AND the backup file is nil-or-absent. The check is at import.go:1070-1078.
Common situations: Exporting from a SiYuan version that stored encryption identity in a different location than the current version expects. Partial export that omitted the .siyuan/ directory or the backup file. Manual deletion of encryption files from the Data.zip. Conf.json edited to set Encrypted=true without providing BoxCrypt.
Related errors
- invalid imported notebook identity [%s]: %w
- notebook [%s] has conflicting normal and encrypted identitie
- imported notebook [%s] contains encrypted payload without id
- read imported notebook conf [%s] failed: %w
- parse imported notebook conf [%s] failed: %w
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/0dc638c3c67ac24f.
Report an issue: GitHub.