siyuan-note/siyuan · error

unmarshal workspace conf [%s] failed: %s

Error message

unmarshal workspace conf [%s] failed: %s

What it means

After successfully reading workspace.json, ReadWorkspacePaths parses it as a JSON array of strings with gulu.JSON.UnmarshalJSON into []string. Malformed JSON (or a non-array JSON value such as an object or number) fails to unmarshal and is reported as 'unmarshal workspace conf [%s] failed: %s'.

Source

Thrown at kernel/util/working.go:423

	}
	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)
		}

		d = strings.TrimRight(d, " \t\n") // 去掉工作空间路径尾部空格 https://github.com/siyuan-note/siyuan/issues/6353
		d = filepath.Clean(d)             // 归一化路径分隔符,清理历史持久化的斜杠差异(如 D:/foo 与 D:\foo) https://github.com/siyuan-note/siyuan/issues/17862
		if gulu.File.IsDir(d) {
			tmp = append(tmp, d)
		} else {
			logging.LogWarnf("workspace path [%s] is not a dir", d)

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Validate the file with a JSON linter and fix the syntax error
  2. Replace a badly corrupted workspace.json with a hand-reconstructed JSON array of your workspace paths
  3. Restore the file from backup if one exists
  4. Avoid hand-editing; let the SiYuan workspace switcher manage the file

Example fix

// before: workspace.json
{"workspaces": ["/home/u/ws"]}   // object, not array
// after
["/home/u/ws"]
Defensive patterns

Strategy: validation

Validate before calling

data, _ := os.ReadFile(confPath)
var probe []string
if err := json.Unmarshal(data, &probe); err != nil {
    // corrupted or wrong shape: reset to empty registry before calling the API
    os.WriteFile(confPath, []byte("[]"), 0644)
}

Try / catch

paths, err := util.ReadWorkspacePaths()
if err != nil {
    if strings.Contains(err.Error(), "unmarshal workspace conf") {
        backup(confPath)               // keep corrupted file for recovery
        os.WriteFile(confPath, []byte("[]"), 0644)
        paths, err = util.ReadWorkspacePaths()
    }
    if err != nil { return err }
}

Prevention

When it happens

Trigger: Any workspace API call when workspace.json contains invalid JSON — truncated file (crash mid-write), hand-edited with a syntax error, BOM or wrong encoding, or a JSON object/string instead of the expected array of path strings.

Common situations: Manual editing of workspace.json with trailing commas or comments; a crash or power loss leaving a partially written file; another tool overwriting the file with a different schema; non-UTF8 encoding after external modification.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


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