siyuan-note/siyuan · error

read workspace conf [%s] failed: %s

Error message

read workspace conf [%s] failed: %s

What it means

ReadWorkspacePaths reads the global workspace registry at ~/.config/siyuan/workspace.json (a JSON array of workspace directory paths). If the file cannot be read at all (missing, permission denied, is a directory), it logs and returns 'read workspace conf [%s] failed: %s'. All workspace operations (open, create, remove, list) depend on this call.

Source

Thrown at kernel/util/working.go:416

	targetLower := strings.ToLower(target)
	var result []string
	for _, p := range paths {
		if strings.ToLower(p) == targetLower {
			continue
		}
		result = append(result, p)
	}
	return result
}

func ReadWorkspacePaths() (ret []string, err error) {
	ret = []string{}
	workspaceConf := filepath.Join(HomeDir, ".config", "siyuan", "workspace.json")
	data, err := os.ReadFile(workspaceConf)
	if err != nil {
		msg := fmt.Sprintf("read workspace conf [%s] failed: %s", workspaceConf, err)
		logging.LogError(msg)
		err = errors.New(msg)
		return
	}

	if err = gulu.JSON.UnmarshalJSON(data, &ret); err != nil {
		msg := fmt.Sprintf("unmarshal workspace conf [%s] failed: %s", workspaceConf, err)
		logging.LogError(msg)
		err = errors.New(msg)
		return
	}

	var tmp []string
	workspaceBaseDir := filepath.Dir(HomeDir)
	for _, d := range ret {
		if ContainerIOS == Container && strings.Contains(d, "/Documents/") {
			// iOS 端沙箱路径会变化,需要转换为相对路径再拼接当前沙箱中的工作空间基路径
			d = d[strings.Index(d, "/Documents/")+len("/Documents/"):]
			d = filepath.Join(workspaceBaseDir, d)
		}

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Check that ~/.config/siyuan/workspace.json exists; on a fresh install create it as an empty JSON array: []
  2. Fix file permissions so the kernel user can read it (chmod/chown)
  3. If the path is a directory or corrupted beyond repair, back it up and replace it with []
  4. Verify the HomeDir resolution matches expectations when running under a service account

Example fix

# before
ls -l ~/.config/siyuan/workspace.json  # permission denied
# after
sudo chown $USER ~/.config/siyuan/workspace.json
chmod 600 ~/.config/siyuan/workspace.json
# or on first run:
echo '[]' > ~/.config/siyuan/workspace.json
Defensive patterns

Strategy: validation

Validate before calling

workspaceConf := filepath.Join(home, ".config", "siyuan", "workspace.json")
if info, err := os.Stat(workspaceConf); os.IsNotExist(err) {
    os.MkdirAll(filepath.Dir(workspaceConf), 0755)
    os.WriteFile(workspaceConf, []byte("[]"), 0644) // bootstrap empty registry
} else if err == nil && info.IsDir() {
    return fmt.Errorf("%s is a directory", workspaceConf)
}

Try / catch

paths, err := util.ReadWorkspacePaths()
if err != nil {
    if strings.Contains(err.Error(), "read workspace conf") {
        // first run or unreadable conf: bootstrap with empty list
        os.WriteFile(confPath, []byte("[]"), 0644)
        paths, err = util.ReadWorkspacePaths()
    }
    if err != nil { return err }
}

Prevention

When it happens

Trigger: Any caller (getWorkspaces, setWorkspaceDir, createWorkspaceDir, removeWorkspaceDir, removeWorkspaceDirPhysically) invoking ReadWorkspacePaths when os.ReadFile(~/.config/siyuan/workspace.json) fails — typically the file doesn't exist yet on first run, or its permissions/ownership prevent reading, or the path is a directory.

Common situations: First launch before workspace.json was ever created; config directory owned by another user after sudo-installed kernel; roaming-profile/backup tools replacing the file with a directory; disk errors.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/00b3129de0022f79. Report an issue: GitHub.