siyuan-note/siyuan · error
invalid session id
Error message
invalid session id
What it means
gulu.JSON.UnmarshalJSON failed to decode the contents of ~/.config/siyuan/workspace.json into []string inside util.ReadWorkspacePaths. The file exists but is not valid JSON of the expected shape — typically a JSON array of workspace path strings. Corruption usually comes from manual edits, a truncated write (crash during save), or another tool rewriting the file.
Source
Thrown at kernel/agent/runtime.go:125
mode, err := resolveSessionPermissionModeLocked(sessionID, nil)
if err != nil {
return nil, err
}
controller.allowSession.Store(mode == AgentPermissionAllowSession)
sessionPermissionControllers.Store(sessionID, controller)
return controller, nil
}
func unregisterSessionPermissionController(sessionID string, controller *sessionPermissionController) {
if sessionID == "" || controller == nil {
return
}
sessionPermissionControllers.CompareAndDelete(sessionID, controller)
}
func SetSessionPermissionMode(sessionID, mode string) error {
if sessionID == "" || !isValidSessionID(sessionID) {
return fmt.Errorf("invalid session id")
}
if !validAgentPermissionMode(mode) {
return fmt.Errorf("invalid agent permission mode")
}
lock := sessionLock(sessionID)
lock.Lock()
defer lock.Unlock()
if _, err := os.Stat(filepath.Join(sessionsDir(), sessionID, "session.json")); err != nil {
return err
}
runtime, err := loadRuntimeLocked(sessionID)
if err != nil {
return err
}
runtime.PermissionMode = mode
runtime.AlwaysAllow = false
if err = writeRuntimeLocked(sessionID, runtime); err != nil {
return errView on GitHub (pinned to afa823b6b4)
Solutions
- Open ~/.config/siyuan/workspace.json and validate it: it must be a plain JSON array of strings, e.g. ["/home/me/SiYuan"]
- Fix the syntax error, or simply delete/rename the file — the app treats it as fresh state and re-registers the current workspace
- If workspaces listed there matter, note the paths first, then recreate the file with those paths as a clean array
- Exclude ~/.config/siyuan from sync/merge tools to avoid conflict-corrupted writes in the future
Example fix
// before (corrupt) ["/home/me/SiYuan", "/data/ws",] // after (valid) [ "/home/me/SiYuan", "/data/ws" ]
Defensive patterns
Strategy: validation
Validate before calling
data, err := os.ReadFile(workspaceConf)
if err == nil && !json.Valid(data) {
// refuse to hand corrupt config to the kernel; back it up and start fresh
_ = os.Rename(workspaceConf, workspaceConf+".bak")
} Type guard
func isValidWorkspaceConf(data []byte) bool {
var paths []string
return json.Unmarshal(data, &paths) == nil
} Try / catch
paths, err := util.ReadWorkspacePaths()
if err != nil && strings.Contains(err.Error(), "unmarshal workspace conf") {
_ = os.Rename(workspaceConf, workspaceConf+".corrupt")
paths, err = util.ReadWorkspacePaths() // regenerates from fresh state
} Prevention
- Never hand-edit workspace.json while the kernel is running; use the UI to switch workspaces
- Validate with json.Valid before external tooling rewrites the file
- Exclude ~/.config/siyuan from sync/merge tools that produce conflict artifacts
When it happens
Trigger: Hand-editing workspace.json and leaving a trailing comma/missing bracket; the process being killed mid-write leaving a partial file; replacing the file with an object {"path": ...} instead of an array; encoding issues (BOM, double UTF-8 encoding) from external editors.
Common situations: Users manually reordering or pruning workspace entries; power loss during workspace switching; sync tools (Dropbox etc.) conflict-merging the dotfile; scripts generating the file with a different schema.
Related errors
- unsupported agent runtime schema version: %d
- unmarshal box document metadata failed: %w
- unmarshal notebook crypt backup failed: %w
- decode session data failed: %w
- decode existing session data failed: %w
AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18).
Data as JSON: /api/errors/15c95dce9a9d96a7.
Report an issue: GitHub.