{"record":{"id":"3902b6c6c33acf29","repo":"siyuan-note/siyuan","slug":"can-not-open-file-just-support-open-folder-only","errorCode":null,"errorMessage":"can not open file, just support open folder only","messagePattern":"can not open file, just support open folder only","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/mount.go","lineNumber":449,"sourceCode":"\t\t}\n\n\t\tif box := Conf.Box(boxID); nil != box {\n\t\t\tboxConf := box.GetConf()\n\t\t\tboxConf.Closed = true\n\t\t\tboxConf.Sort = sort\n\t\t\tbox.SaveConf(boxConf)\n\t\t}\n\n\t\ttask.AppendAsyncTaskWithDelay(task.PushMsg, 3*time.Second, util.PushErrMsg, Conf.Language(244), 7000)\n\t\tgo func() {\n\t\t\t// 每次打开帮助文档时自动检查版本更新并提醒 https://github.com/siyuan-note/siyuan/issues/5057\n\t\t\ttime.Sleep(time.Second * 10)\n\t\t\tCheckUpdate(true)\n\t\t}()\n\t}\n\n\tif !gulu.File.IsDir(localPath) {\n\t\treturn false, errors.New(\"can not open file, just support open folder only\")\n\t}\n\n\tfor _, box := range Conf.GetOpenedBoxes() {\n\t\tif box.ID == boxID {\n\t\t\treturn true, nil\n\t\t}\n\t}\n\n\t// 加密笔记本必须先通过 UnlockBox 解出 DEK，否则拒绝挂载。Mount 本身不接收密码，\n\t// 前端流程为：先调 /api/notebook/unlockBox 解锁，再调 openNotebook 挂载。\n\t// 使用 IsEncryptedBox 统一判定（含 backup fallback，不依赖 conf 完整性）。\n\tif IsEncryptedBox(boxID) && !IsBoxUnlocked(boxID) {\n\t\treturn false, errors.New(\"encrypted notebook locked, please unlock it first\")\n\t}\n\n\tbox := &Box{ID: boxID}\n\tboxConf := box.GetConf()\n\tboxConf.Closed = false","sourceCodeStart":431,"sourceCodeEnd":467,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/mount.go#L431-L467","documentation":"Returned in the user-guide/mount path of kernel/model/mount.go:449 when the resolved localPath is not a directory. This is the open (openNotebook/mountBox) counterpart of [801]: the path under util.DataDir/<boxID> exists as something other than a folder, so opening it as a notebook is refused.","triggerScenarios":"Calling openNotebook for a boxID whose data directory was replaced by a regular file, or for the user-guide notebook when its on-disk folder was swapped for a file.","commonSituations":"Manual tampering under data/, broken extraction of a user-guide archive, or filesystem corruption that converted a dir to a file.","solutions":["Inspect <workspace>/data/<boxID> and confirm it is a directory; if a file is there, remove or rename it and recreate/restore the notebook folder.","For the user guide, let SiYuan regenerate it (close and re-open the guide from settings) rather than hand-creating files.","Restore from history/repo if the folder contents are gone."],"exampleFix":"# before\n$ ls data/<boxID>  # shows a regular file\n# after\n$ rm data/<boxID>\n# then retry openNotebook; the kernel re-creates the user guide if needed","handlingStrategy":"validation","validationCode":"p := filepath.Join(util.DataDir, boxID)\nif info, err := os.Stat(p); err == nil && !info.IsDir() {\n    return fmt.Errorf(\"%%s is not a directory; cannot open as notebook\", p)\n}\n_, err := model.Mount(boxID)\nreturn err","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not place files where a notebook directory is expected.","For the user guide, use the in-app action rather than reconstructing paths by hand."],"tags":["notebook","mount","filesystem","user-guide"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}