siyuan-note/siyuan · error

read session file failed: %w

Error message

read session file failed: %w

What it means

While loading the current session for a save, os.ReadFile(path) failed with an error other than os.IsNotExist — i.e. the file is probably there (or the directory is inaccessible) but the kernel cannot read it (kernel/agent/session.go:379-380). The raw OS error is wrapped with %w, so the cause (permission, I/O, path length) is visible in the message.

Source

Thrown at kernel/agent/session.go:380

				}
				return currentRevision, existingData, nil
			}
			if meta.ExpectedRevision != nil && *meta.ExpectedRevision != currentRevision {
				return currentRevision, nil, ErrSessionConflict
			}
			for k, v := range existingData {
				if _, ok := newData[k]; !ok {
					// messages 是已废弃的旧会话字段,不再带入新格式;其他未知字段原样保留,
					// 避免前后端版本不一致时擦除较新版本写入的数据。
					if k != "messages" && k != "expectedRevision" && k != "commitTurnID" &&
						k != "recoveryTurnID" && k != "recoveryState" && k != "recoveryRevision" && k != "agentRunning" {
						newData[k] = v
					}
				}
			}
		}
	} else if err != nil && !os.IsNotExist(err) {
		return 0, nil, fmt.Errorf("read session file failed: %w", err)
	} else if meta.ExpectedRevision != nil && *meta.ExpectedRevision != 0 {
		return 0, nil, ErrSessionConflict
	}
	if commitTurnID != "" {
		runtime, err := loadRuntimeLocked(meta.ID)
		if err != nil {
			return currentRevision, nil, fmt.Errorf("read agent runtime failed: %w", err)
		}
		if runtime.ActiveTurn != nil {
			if runtime.ActiveTurn.TurnID != commitTurnID {
				return currentRevision, nil, ErrSessionConflict
			}
			if !isRuntimeTurnTerminal(runtime.ActiveTurn) {
				return currentRevision, nil, ErrRuntimeNotFinalized
			}
			if err := applyRuntimeTurnToSessionLocked(newData, runtime.ActiveTurn); err != nil {
				return currentRevision, nil, err
			}

View on GitHub (pinned to afa823b6b4)

Solutions

  1. Read the wrapped errno in the message: EACCES/EPERM → fix ownership (chown/chmod) on workspace/data/storage/ai/agent; EIO/ENOTCONN → remount the workspace volume
  2. Verify the kernel process user can cat the session.json file
  3. On Windows, exclude the workspace from antivirus real-time scanning or wait for the backup lock to release
  4. Retry the save only after the underlying access problem is fixed
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight: kernel process must be able to read the session dir
// (run as the same user the kernel runs under)
// ls -la <workspace>/data/storage/ai/agent/sessions/<id>/session.json

Type guard

null

Try / catch

catch (e) {
  if (/read session file failed/.test(e?.data?.msg ?? '')) {
    // inspect wrapped errno; fix ownership/mount, then retry once
  }
}

Prevention

When it happens

Trigger: POST /api/ai/agent/saveSession when data/storage/ai/agent/sessions/<id>/session.json or a parent directory has wrong ownership/permissions (EACCES), the workspace is on an unmounted/network volume (EIO, ENOTCONN), or the path exceeds OS limits. Distinct from a first-time save: file-not-exist is expected and handled, everything else is fatal.

Common situations: Workspace copied between machines with different UIDs; running the kernel under a service account without read access; antivirus or backup software holding an exclusive lock on Windows; a removable/network drive dropping out mid-session.

Related errors


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