siyuan-note/siyuan · error

unsupported agent runtime schema version: %d

Error message

unsupported agent runtime schema version: %d

What it means

filelock.WriteFile failed to persist ~/.config/siyuan/workspace.json inside util.WriteWorkspacePaths. The JSON serialized fine but the disk write failed: no permission on ~/.config/siyuan, a read-only home filesystem, disk full, or the filelock layer unable to acquire/create its lock artifacts. The underlying error is appended.

Source

Thrown at kernel/agent/runtime.go:204

func runtimePath(sessionID string) string {
	return filepath.Join(sessionsDir(), sessionID, "runtime.json")
}

func loadRuntimeLocked(sessionID string) (*agentRuntime, error) {
	data, err := os.ReadFile(runtimePath(sessionID))
	if err != nil {
		if os.IsNotExist(err) {
			return &agentRuntime{SchemaVersion: 1, SessionID: sessionID}, nil
		}
		return nil, err
	}
	var runtime agentRuntime
	if err := gulu.JSON.UnmarshalJSON(data, &runtime); err != nil {
		return nil, err
	}
	if runtime.SchemaVersion > 1 {
		return nil, fmt.Errorf("unsupported agent runtime schema version: %d", runtime.SchemaVersion)
	}
	if runtime.SessionID != "" && runtime.SessionID != sessionID {
		return nil, fmt.Errorf("agent runtime session id mismatch")
	}
	if runtime.Revision < 0 {
		return nil, fmt.Errorf("invalid agent runtime revision")
	}
	if runtime.ActiveTurn != nil {
		if runtime.ActiveTurn.TurnID == "" {
			return nil, fmt.Errorf("invalid agent runtime turn id")
		}
		switch runtime.ActiveTurn.State {
		case "running", "finished", "interrupted":
		default:
			return nil, fmt.Errorf("invalid agent runtime turn state")
		}
	}
	if runtime.SchemaVersion == 0 {

View on GitHub (pinned to afa823b6b4)

Solutions

  1. Read the appended error: 'permission denied' -> chown -R <kerneluser> ~/.config/siyuan (or chmod u+w); 'no space left on device' -> free space
  2. Ensure the service/container sets HOME to a writable directory for the user the kernel runs as
  3. Verify the directory exists: mkdir -p ~/.config/siyuan with the right ownership
  4. On NFS-like filesystems, move the config dir to local storage or ensure lock files can be created in it

Example fix

# before: container runs as root but HOME volume owned by uid 1000
HOME=/home/siyuan

# after: align user and ownership
user: "1000:1000"
volumes: ["/path/home:/home/siyuan"]
# and on the host: chown -R 1000:1000 /path/home/.config/siyuan
Defensive patterns

Strategy: retry

Validate before calling

confDir := filepath.Join(home, ".config", "siyuan")
if err := os.MkdirAll(confDir, 0755); err != nil {
    return fmt.Errorf("cannot prepare %s: fix permissions before workspace switch", confDir)
}

Type guard

null

Try / catch

err := util.WriteWorkspacePaths(paths)
if err != nil && strings.Contains(err.Error(), "write workspace conf") {
    time.Sleep(500 * time.Millisecond) // lock contention is transient
    err = util.WriteWorkspacePaths(paths)
}

Prevention

When it happens

Trigger: Switching or closing a workspace when the kernel user cannot write ~/.config/siyuan (ownership mismatch after container/user migration), HOME points somewhere read-only (systemd unit without proper env), disk quota exhausted, or an NFS/home mount denying the lock file creation used by filelock.

Common situations: Docker or systemd deployments where HOME is unset or owned by root; multi-user machines with restrictive home permissions; disk-full events; network home directories (NFS/Lustre) that interact badly with lock files.

Related errors


AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18). Data as JSON: /api/errors/ad34bd7739dbb499. Report an issue: GitHub.