{"record":{"id":"7d8f38d59f39d110","repo":"siyuan-note/siyuan","slug":"conf-language-393-flashcard","errorCode":null,"errorMessage":"Conf.Language(393)","messagePattern":"Conf\\.Language\\(393\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/flashcard.go","lineNumber":55,"sourceCode":"\t\"github.com/siyuan-note/siyuan/kernel/cache\"\n\t\"github.com/siyuan-note/siyuan/kernel/sql\"\n\t\"github.com/siyuan-note/siyuan/kernel/treenode\"\n\t\"github.com/siyuan-note/siyuan/kernel/util\"\n)\n\n// ValidateFlashcardBlockIDs 只允许普通笔记本中可确认存在的块进入全局闪卡存储。\nfunc ValidateFlashcardBlockIDs(blockIDs []string) error {\n\treturn validateFlashcardBlockIDs(blockIDs, treenode.GetBlockTree, IsEncryptedBox)\n}\n\nfunc validateFlashcardBlockIDs(blockIDs []string, getBlockTree func(string) *treenode.BlockTree, isEncryptedBox func(string) bool) error {\n\tfor _, blockID := range blockIDs {\n\t\tbt := getBlockTree(blockID)\n\t\tif bt == nil {\n\t\t\treturn errors.New(Conf.Language(180))\n\t\t}\n\t\tif isEncryptedBox(bt.BoxID) {\n\t\t\treturn errors.New(Conf.Language(393))\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc validateFlashcardTree(rootID string) error {\n\treturn ValidateFlashcardBlockIDs([]string{rootID})\n}\n\nfunc isSupportedFlashcardBlock(blockID string) bool {\n\tbt := treenode.GetBlockTreeInExactBox(blockID, \"\")\n\treturn bt != nil && !IsEncryptedBox(bt.BoxID)\n}\n\nfunc filterSupportedFlashcards(cards []riff.Card) (ret []riff.Card) {\n\tfor _, card := range cards {\n\t\tif card == nil || !isSupportedFlashcardBlock(card.BlockID()) {\n\t\t\tcontinue","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/flashcard.go#L37-L73","documentation":"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.","triggerScenarios":"Calling flashcard creation/validation APIs with a blockID whose bt.BoxID satisfies isEncryptedBox (notebook opened with the encrypted-notebook feature / password-protected data).","commonSituations":"Batch-selecting cards across all notebooks where some are encrypted; scripted flashcard export iterating every box without filtering encrypted ones.","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"],"exampleFix":"// before\napi.post('/api/riff/createDeckWithBlocks', {deckName, blockIDs})\n// after\nconst encBoxes = new Set((await api.post('/api/notebook/lsNotebooks')).data.notebooks.filter(n => n.isEncrypted).map(n => n.id))\napi.post('/api/riff/createDeckWithBlocks', {deckName, blockIDs: blockIDs.filter(id => !encBoxes.has(boxOf(id)))})","handlingStrategy":"validation","validationCode":"const enc = new Set((await api.post('/api/notebook/lsNotebooks')).data.notebooks.filter(n => n.closed === false && n.isEncrypted).map(n => n.id))\nconst usable = blockIDs.filter(id => !enc.has(getBoxIDOf(id)))","typeGuard":"const isEncryptedNotebook = (notebook) => !!notebook.isEncrypted;","tryCatchPattern":"try { await createDeckWithBlocks(ids) } catch (e) { if (e.msg === L(393)) notifyUser('Encrypted notebooks do not support flashcards') }","preventionTips":["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"],"tags":["flashcards","encryption","unsupported-operation","i18n"],"backgroundTag":"unsupported-operation","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}