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
- Detect read-only state before writing and degrade gracefully (skip the put, keep state in memory)
- Retry the put later when the workspace is reopened in read-write mode
- Inform the user that the setting/state could not be persisted because the kernel is read-only
- 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
- Persist plugin state opportunistically, tolerating read-only sessions
- Queue writes and flush them when the workspace is next writable
- Surface a user-facing notice when a required write is blocked by read-only mode
- Avoid unconditional writes on plugin load, which fire during read-only sessions
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
- failed to make directory
- failed to remove storage path from watcher
- failed to write file
- panic during siyuan.storage.get
- panic during siyuan.storage.put
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)