siyuan-note/siyuan · error

Conf.Language(393)

Error message

Conf.Language(393)

What it means

validateFlashcardBlockIDs rejects block IDs that belong to an encrypted notebook: Conf.Language(393) reads 'Encrypted notebooks do not support this operation'. Flashcard creation from blocks inside encrypted boxes is unsupported by design and the request is refused before any deck mutation.

Solutions

  1. Filter out block IDs belonging to encrypted notebooks before calling the flashcard API
  2. Check notebook attributes (isEncryptedBox / notebook config) client-side to exclude those boxes
  3. Create the flashcards from the same blocks in a non-encrypted notebook if the workflow requires it

Example fix

// before
api.post('/api/riff/createDeckWithBlocks', {deckName, blockIDs})
// after
const encBoxes = new Set((await api.post('/api/notebook/lsNotebooks')).data.notebooks.filter(n => n.isEncrypted).map(n => n.id))
api.post('/api/riff/createDeckWithBlocks', {deckName, blockIDs: blockIDs.filter(id => !encBoxes.has(boxOf(id)))})
Defensive patterns

Strategy: validation

Validate before calling

const enc = new Set((await api.post('/api/notebook/lsNotebooks')).data.notebooks.filter(n => n.closed === false && n.isEncrypted).map(n => n.id))
const usable = blockIDs.filter(id => !enc.has(getBoxIDOf(id)))

Type guard

const isEncryptedNotebook = (notebook) => !!notebook.isEncrypted;

Try / catch

try { await createDeckWithBlocks(ids) } catch (e) { if (e.msg === L(393)) notifyUser('Encrypted notebooks do not support flashcards') }

Prevention

When it happens

Trigger: Calling flashcard creation/validation APIs with a blockID whose bt.BoxID satisfies isEncryptedBox (notebook opened with the encrypted-notebook feature / password-protected data).

Common situations: Batch-selecting cards across all notebooks where some are encrypted; scripted flashcard export iterating every box without filtering encrypted ones.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/7d8f38d59f39d110. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/flashcard.go:55

	"github.com/siyuan-note/siyuan/kernel/cache"
	"github.com/siyuan-note/siyuan/kernel/sql"
	"github.com/siyuan-note/siyuan/kernel/treenode"
	"github.com/siyuan-note/siyuan/kernel/util"
)

// ValidateFlashcardBlockIDs 只允许普通笔记本中可确认存在的块进入全局闪卡存储。
func ValidateFlashcardBlockIDs(blockIDs []string) error {
	return validateFlashcardBlockIDs(blockIDs, treenode.GetBlockTree, IsEncryptedBox)
}

func validateFlashcardBlockIDs(blockIDs []string, getBlockTree func(string) *treenode.BlockTree, isEncryptedBox func(string) bool) error {
	for _, blockID := range blockIDs {
		bt := getBlockTree(blockID)
		if bt == nil {
			return errors.New(Conf.Language(180))
		}
		if isEncryptedBox(bt.BoxID) {
			return errors.New(Conf.Language(393))
		}
	}
	return nil
}

func validateFlashcardTree(rootID string) error {
	return ValidateFlashcardBlockIDs([]string{rootID})
}

func isSupportedFlashcardBlock(blockID string) bool {
	bt := treenode.GetBlockTreeInExactBox(blockID, "")
	return bt != nil && !IsEncryptedBox(bt.BoxID)
}

func filterSupportedFlashcards(cards []riff.Card) (ret []riff.Card) {
	for _, card := range cards {
		if card == nil || !isSupportedFlashcardBlock(card.BlockID()) {
			continue

View on GitHub (pinned to 9f775e8a12)