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
- Filter out block IDs belonging to encrypted notebooks before calling the flashcard API
- Check notebook attributes (isEncryptedBox / notebook config) client-side to exclude those boxes
- 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
- Filter encrypted notebooks out of any batch flashcard workflow
- Check notebook encryption flags when enumerating boxes
- Surface the limitation in UI before users select blocks in encrypted notebooks
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
- 26
- conditional replacement of encrypted documents is not…
- Conf.Language(180)
- Conf.Language(313)
- Conf.Language(313)
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()) {
continueView on GitHub (pinned to 9f775e8a12)