siyuan-note/siyuan · critical
encrypted notebook [ ] has no valid identity
Error message
encrypted notebook [%s] has no valid identity
What it means
For a notebook whose conf.json declares Encrypted=true, validateImportedNotebookIdentities needs a usable BoxEncryption identity: prefer a validated boxConf.BoxCrypt, otherwise fall back to the backup file. If neither is present or valid, it returns 'encrypted notebook [%s] has no valid identity', refusing the import — importing an encrypted notebook without its key envelope would produce permanently unreadable content.
Solutions
- Re-export/re-package the notebook from the source workspace including the full .siyuan directory so BoxCrypt/backup key material is present.
- Restore the notebook's encryption backup file from sync history or snapshots, then retry the import.
- If the notebook should be plaintext, decrypt it in the source workspace first (with its keys available there), then re-export and import.
- Never regenerate MasterSalt or key material to force the import — recover the original keys via the recovery phrase instead.
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 && !conf.boxCrypt && !hasBackup) {
throw new Error('encrypted notebook package lacks key material; re-export with .siyuan included');
} Try / catch
try {
await importData(src);
} catch (e) {
if (/has no valid identity/.test(e.msg)) {
console.error('Re-export including encryption metadata, or restore the backup file / recover keys via recovery phrase');
}
throw e;
} Prevention
- Include the entire notebook directory (not just .sy files) in transfers of encrypted notebooks
- Recover keys via the recovery phrase instead of attempting to regenerate them
- Decrypt in the source workspace before exporting if plaintext import is desired
When it happens
Trigger: ImportData importing a notebook with conf.json {"encrypted": true} but with a missing/nil BoxCrypt field AND a missing or invalid encryption backup file, so no validated identity can be established.
Common situations: 1) User hand-copied only the .sy files, omitting .siyuan encryption metadata. 2) Archive builder excluded hidden .siyuan directory. 3) Backup file exists but failed validation (see index 1496) so the fallback is nil. 4) Notebook encrypted after export; archive predates encryption.
Related errors
- invalid imported notebook identity
- notebook [ ] has conflicting normal and encrypted identities
- Conf.Language(388) with escaped relative path…
- 199
- block not found or its encrypted notebook is locked
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/0dc638c3c67ac24f.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/import.go:1360
}
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 9f775e8a12)