siyuan-note/siyuan · error

Encrypted notebooks do not support this operation

Error message

Encrypted notebooks do not support this operation

What it means

The import target is an encrypted notebook (IsEncryptedBox) and the archive contains a storage/riff directory, i.e. flashcard deck data. Flashcard decks are stored in the global plaintext directory data/storage/riff and merged into the built-in deck, which encrypted notebooks cannot participate in, so importSY0 aborts early with Language(313) 'Encrypted notebooks do not support this operation'. If a notebook was being created for the import, the deferred rollback removes it.

Source

Thrown at kernel/model/import.go:329

			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 := sharedBlockIDs
	if nil == blockIDs {
		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

View on GitHub (pinned to afa823b6b4)

Solutions

  1. Import into a non-encrypted notebook instead
  2. Or strip flashcard data from the archive (remove storage/riff and riff-decks attributes) before importing - the cards will be lost
  3. Keep the notebook unencrypted if preserving flashcards matters more than encryption
Defensive patterns

Strategy: validation

Validate before calling

func archiveHasRiffStorage(zipPath string) bool {
    r, err := zip.OpenReader(zipPath)
    if err != nil {
        return false
    }
    defer r.Close()
    for _, f := range r.File {
        if strings.Contains(f.Name, "storage/riff/") {
            return true
        }
    }
    return false
}

if model.IsEncryptedBox(boxID) && archiveHasRiffStorage(zipPath) {
    // refuse early: encrypted targets cannot take flashcard data
}

Type guard

func isEncryptedUnsupported(err error) bool {
    return err != nil && err.Error() == model.Conf.Language(313)
}

Try / catch

if err := model.ImportSY(zipPath, boxID, toPath); err != nil {
    if err.Error() == model.Conf.Language(313) {
        // retry against a non-encrypted notebook, or strip flashcard data from the archive
    }
}

Prevention

When it happens

Trigger: Any importSY-family call into an encrypted box with an archive exported from a notebook whose documents carry flashcards - the export includes storage/riff/<deck> files. Detected right after target resolution, before trees are parsed.

Common situations: Migrating spaced-repetition material into an encrypted notebook. Users enabling notebook encryption and then trying to restore old flashcard-bearing exports.

Related errors


AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18). Data as JSON: /api/errors/fd2d7059419568b6. Report an issue: GitHub.