siyuan-note/siyuan · error

The current kernel is in read-only mode, storage.put is not…

Error message

The current kernel is in read-only mode, storage.put is not allowed

What it means

Rejected when siyuan.storage.put(path, content) is called while the SiYuan kernel is running in read-only mode (util.ReadOnly). Read-only mode blocks all mutating operations to protect data; plugin storage writes are refused even though the path is valid and the plugin itself is loaded.

Solutions

  1. Detect read-only state before writing and degrade gracefully (skip the put, keep state in memory)
  2. Retry the put later when the workspace is reopened in read-write mode
  3. Inform the user that the setting/state could not be persisted because the kernel is read-only
  4. Relaunch SiYuan without the read-only option if persistent writes are required

Example fix

// before
await siyuan.storage.put("state.json", JSON.stringify(state));
// after
try {
  await siyuan.storage.put("state.json", JSON.stringify(state));
} catch (e) {
  if (String(e.message).includes("read-only mode")) {
    console.warn("Kernel is read-only; keeping state in memory only");
  } else { throw e; }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// probe with a harmless write on init to learn mode
canWrite = await siyuan.storage.put(".probe", "1").then(() => true, () => false);

Type guard

null

Try / catch

try { await siyuan.storage.put(path, content); } catch (e) { if (String(e.message).includes("read-only mode")) { keepInMemoryOnly(); } else { throw e; } }

Prevention

When it happens

Trigger: The kernel was started with a read-only flag or the workspace is in a read-only state (e.g. protected mode) and the plugin calls siyuan.storage.put; automated plugin tasks writing on boot while the user opened the workspace read-only.

Common situations: Running SiYuan with the read-only launch option for safe browsing; CI/automation sessions with read-only workspaces; plugins that cache state via storage.put unconditionally on startup.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/26f88552fca07ee6. Report an issue: GitHub.

Appendix: source

Thrown at kernel/plugin/api_storage.go:247

	lo.Must0(storage.Set("put", rt.ToValue(func(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
		promise, resolve, reject := rt.NewPromise()

		var argErr error
		var path, content string
		if len(call.Arguments) < 2 {
			argErr = fmt.Errorf("path and content required")
		} else {
			path = call.Argument(0).String()
			content = call.Argument(1).String()
		}

		runErr := p.worker.Run(func(rt *goja.Runtime) (result any, err error) {
			if argErr != nil {
				err = argErr
				return
			}
			if util.ReadOnly {
				err = fmt.Errorf("The current kernel is in read-only mode, storage.put is not allowed")
				return
			}

			abs, resolveErr := resolvePath(path)
			if resolveErr != nil {
				err = resolveErr
				return
			}

			go func() (result any, err error) {
				defer func() {
					if r := recover(); r != nil {
						err = fmt.Errorf("panic during siyuan.storage.put: %v", r)
					}

					p.worker.Run(func(rt *goja.Runtime) (_ any, _ error) {
						if lo.IsNil(err) {
							if resolveErr := resolve(result); resolveErr != nil {

View on GitHub (pinned to 9f775e8a12)