siyuan-note/siyuan · error

can not open file, just support open folder only

Error message

can not open file, just support open folder only

What it means

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.

Source

Thrown at kernel/model/mount.go:449

		}

		if box := Conf.Box(boxID); nil != box {
			boxConf := box.GetConf()
			boxConf.Closed = true
			boxConf.Sort = sort
			box.SaveConf(boxConf)
		}

		task.AppendAsyncTaskWithDelay(task.PushMsg, 3*time.Second, util.PushErrMsg, Conf.Language(244), 7000)
		go func() {
			// 每次打开帮助文档时自动检查版本更新并提醒 https://github.com/siyuan-note/siyuan/issues/5057
			time.Sleep(time.Second * 10)
			CheckUpdate(true)
		}()
	}

	if !gulu.File.IsDir(localPath) {
		return false, errors.New("can not open file, just support open folder only")
	}

	for _, box := range Conf.GetOpenedBoxes() {
		if box.ID == boxID {
			return true, nil
		}
	}

	// 加密笔记本必须先通过 UnlockBox 解出 DEK,否则拒绝挂载。Mount 本身不接收密码,
	// 前端流程为:先调 /api/notebook/unlockBox 解锁,再调 openNotebook 挂载。
	// 使用 IsEncryptedBox 统一判定(含 backup fallback,不依赖 conf 完整性)。
	if IsEncryptedBox(boxID) && !IsBoxUnlocked(boxID) {
		return false, errors.New("encrypted notebook locked, please unlock it first")
	}

	box := &Box{ID: boxID}
	boxConf := box.GetConf()
	boxConf.Closed = false

View on GitHub (pinned to 251596fc0d)

Solutions

  1. 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.
  2. For the user guide, let SiYuan regenerate it (close and re-open the guide from settings) rather than hand-creating files.
  3. Restore from history/repo if the folder contents are gone.

Example fix

# before
$ ls data/<boxID>  # shows a regular file
# after
$ rm data/<boxID>
# then retry openNotebook; the kernel re-creates the user guide if needed
Defensive patterns

Strategy: validation

Validate before calling

p := filepath.Join(util.DataDir, boxID)
if info, err := os.Stat(p); err == nil && !info.IsDir() {
    return fmt.Errorf("%%s is not a directory; cannot open as notebook", p)
}
_, err := model.Mount(boxID)
return err

Prevention

When it happens

Trigger: 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.

Common situations: Manual tampering under data/, broken extraction of a user-guide archive, or filesystem corruption that converted a dir to a file.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/3902b6c6c33acf29. Report an issue: GitHub.