{"record":{"id":"e3f7376eb00ed30b","repo":"siyuan-note/siyuan","slug":"encrypted-notebooks-do-not-support-this-operation-e3f737","errorCode":null,"errorMessage":"Encrypted notebooks do not support this operation","messagePattern":"Encrypted notebooks do not support this operation","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"kernel/model/file.go","lineNumber":388,"sourceCode":"\treturn ret.String()\n}\n\ntype FileInfo struct {\n\tpath  string\n\tname  string\n\tsize  int64\n\tisdir bool\n}\n\nfunc ListDocTree(boxID, listPath string, sortMode int, flashcard, showHidden bool, maxListCount int) (ret []*File, totals int, err error) {\n\t//os.MkdirAll(\"pprof\", 0755)\n\t//cpuProfile, _ := os.Create(\"pprof/cpu_profile_list_doc_tree\")\n\t//pprof.StartCPUProfile(cpuProfile)\n\t//defer pprof.StopCPUProfile()\n\n\tret = []*File{}\n\tif flashcard && IsEncryptedBox(boxID) {\n\t\treturn nil, 0, errors.New(Conf.Language(313))\n\t}\n\n\tvar deck *riff.Deck\n\tvar deckBlockIDs []string\n\tif flashcard {\n\t\tdeck = Decks[builtinDeckID]\n\t\tif nil == deck {\n\t\t\treturn\n\t\t}\n\n\t\tdeckBlockIDs = deck.GetBlockIDs()\n\t}\n\n\tbox := Conf.Box(boxID)\n\tif nil == box {\n\t\treturn nil, 0, errors.New(Conf.Language(0))\n\t}\n","sourceCodeStart":370,"sourceCodeEnd":406,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/file.go#L370-L406","documentation":"Thrown by ListDocTree when the caller requests flashcard mode (flashcard=true) on a notebook that is encrypted (IsEncryptedBox returns true). Conf.Language(313) = 'Encrypted notebooks do not support this operation'. SiYuan treats encrypted notebooks as crypto-isolated — their content is decrypted on-demand and the flashcard (spaced repetition) subsystem cannot index or enumerate block IDs inside them, so any flashcard-related tree listing is blocked at the entry point.","triggerScenarios":"Calling ListDocTree(boxID, listPath, sortMode, flashcard=true, showHidden, maxListCount) where boxID refers to an encrypted notebook. The flashcard && IsEncryptedBox(boxID) guard at line 387 fires before any deck or file lookup occurs.","commonSituations":"A user opens the flashcard review UI while the active notebook is encrypted. A plugin or API client iterates all notebooks with flashcard=true without filtering out encrypted ones. A notebook was encrypted after the user had already been browsing flashcards in it.","solutions":["Do not pass flashcard=true for encrypted notebooks — check IsEncryptedBox(boxID) before calling ListDocTree.","If flashcard review is needed, move or export the relevant documents to a non-encrypted notebook first.","In UI code, disable or hide the flashcard toggle when the current notebook is encrypted.","For API consumers, query notebook metadata first and skip flashcard mode for encrypted boxes."],"exampleFix":"// before\nfiles, totals, err := model.ListDocTree(boxID, path, sortMode, true, showHidden, max)\n\n// after\nflashcard := true\nif model.IsEncryptedBox(boxID) {\n    flashcard = false\n}\nfiles, totals, err := model.ListDocTree(boxID, path, sortMode, flashcard, showHidden, max)","handlingStrategy":"validation","validationCode":"// Pre-check: skip flashcard mode for encrypted notebooks\nif model.IsEncryptedBox(boxID) {\n    flashcard = false // or return an error / skip the call\n}","typeGuard":"func canUseFlashcard(boxID string) bool {\n    return !model.IsEncryptedBox(boxID)\n}","tryCatchPattern":null,"preventionTips":["Always check IsEncryptedBox(boxID) before passing flashcard=true to ListDocTree.","In UI code, disable the flashcard toggle for encrypted notebooks.","For API consumers iterating all notebooks, filter out encrypted ones for flashcard operations."],"tags":["encryption","flashcard","notebook","access-control"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}