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
- Validate the file with a JSON linter and fix the syntax error
- Replace a badly corrupted workspace.json with a hand-reconstructed JSON array of your workspace paths
- Restore the file from backup if one exists
- 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
- Never hand-edit workspace.json; use the in-app workspace switcher
- Validate JSON before writing the file yourself
- Write the file atomically (temp file + rename) to survive crashes
- Keep the schema strictly as a JSON array of path strings
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
- directory not found: %s
- failed to serialize config.%s: %v
- invalid config.%s: %v
- read workspace conf [%s] failed: %s
- Export failed: %s
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/6de83bd9917622a0.
Report an issue: GitHub.