siyuan-note/siyuan · error

313

313

Error message

Encrypted notebooks do not support this operation

What it means

Returned by importSY (import.go:309) as Conf.Language(313) = "Encrypted notebooks do not support this operation" when the resolved target notebook is encrypted (IsEncryptedBox(boxID)) and the archive contains a storage/riff directory (flashcard data). Flashcard import into encrypted notebooks is disabled because the riff storage layout and key handling for encrypted boxes do not support merging imported decks.

Source

Thrown at kernel/model/import.go:309

			boxConf := box.GetConf()
			boxConf.Icon = filterBoxIcon(importedBoxConf.Icon)
			boxConf.RefCreateSavePath = importedBoxConf.RefCreateSavePath
			boxConf.DocCreateSavePath = importedBoxConf.DocCreateSavePath
			boxConf.DocCreateTemplatePath = importedBoxConf.DocCreateTemplatePath
			boxConf.DailyNoteSavePath = importedBoxConf.DailyNoteSavePath
			boxConf.DailyNoteTemplatePath = importedBoxConf.DailyNoteTemplatePath
			boxConf.SortMode = importedBoxConf.SortMode
			if err = box.SaveConf(boxConf); err != nil {
				return createdBoxID, err
			}
		}
	} else {
		createdBoxID = boxID
	}
	encryptedTarget := IsEncryptedBox(boxID)
	storageRiffDir := filepath.Join(unzipRootPath, "storage", "riff")
	if encryptedTarget && gulu.File.IsExist(storageRiffDir) {
		return createdBoxID, errors.New(Conf.Language(313))
	}
	toPath = normalizeBoxDocTarget(boxID, toPath)

	luteEngine := util.NewLute()
	blockIDs := map[string]string{}
	trees := map[string]*parse.Tree{}
	importedBoxDoc := false
	containsFlashcardAttrs := false

	// 重新生成块 ID
	for i, syPath := range syPaths {
		data, readErr := os.ReadFile(syPath)
		if nil != readErr {
			logging.LogErrorf("read .sy [%s] failed: %s", syPath, readErr)
			err = readErr
			return
		}
		tree, _, parseErr := dataparser.ParseJSON(data, luteEngine.ParseOptions)

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Import into a non-encrypted notebook, or remove the storage/riff folder from the archive before importing into an encrypted target (accepting that flashcard data will be lost).
  2. If flashcards are required on an encrypted notebook, recreate them in the target after import via the flashcard UI.
  3. On the client, detect an encrypted target plus a storage/riff payload and warn the user before upload.
Defensive patterns

Strategy: validation

Validate before calling

encryptedTarget := IsEncryptedBox(boxID)
storageRiffDir := filepath.Join(unzipRootPath, "storage", "riff")
if encryptedTarget && gulu.File.IsExist(storageRiffDir) {
    return errors.New(Conf.Language(313))
}

Type guard

// importBlockedByEncryption reports whether an encrypted target cannot accept the archive's riff dir.
func importBlockedByEncryption(boxID, unzipRoot string) bool {
    return IsEncryptedBox(boxID) &&
        gulu.File.IsExist(filepath.Join(unzipRoot, "storage", "riff"))
}

Try / catch

err := model.ImportSY(zipPath, boxID, toPath)
if err != nil && err.Error() == Conf.Language(313) {
    // either pick a non-encrypted notebook, or drop storage/riff from the archive
}

Prevention

When it happens

Trigger: POST /api/import/importSY (or importSYAuto resolving to an encrypted target) where the .sy.zip was exported from a notebook that had flashcards. The archive carries storage/riff, and the chosen target is an encrypted notebook.

Common situations: User exports a notebook with flashcards and imports it into an encrypted notebook; default notebook on the device is encrypted; policy requires encryption but the source had unencrypted flashcards.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/70995fbf7ee5a5e1. Report an issue: GitHub.