siyuan-note/siyuan · error
The current kernel is in read-only mode, storage.remove is n
Error message
The current kernel is in read-only mode, storage.remove is not allowed
What it means
Thrown by siyuan.storage.remove() when util.ReadOnly is true. The kernel can boot in read-only mode to forbid all mutations; in that mode deletions are rejected before path resolution or filesystem access. The check runs after the argument-count guard but before the storage-root guard.
Source
Thrown at kernel/plugin/api_storage.go:324
// siyuan.storage.remove(path) -> Promise<void>
lo.Must0(storage.Set("remove", rt.ToValue(func(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
promise, resolve, reject := rt.NewPromise()
var argErr error
var path string
if len(call.Arguments) < 1 {
argErr = fmt.Errorf("path required")
} else {
path = call.Argument(0).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.remove is not allowed")
return
}
abs, resolveErr := resolvePath(path)
if resolveErr != nil {
err = resolveErr
return
}
if abs == p.storageDir {
err = fmt.Errorf("cannot remove storage root")
return
}
go func() (result any, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic during siyuan.storage.remove: %v", r)
}View on GitHub (pinned to 251596fc0d)
Solutions
- Detect read-only mode at startup and hide or disable delete features.
- Wrap remove in try/catch and degrade gracefully when the rejection indicates read-only mode.
- Inform the user that the operation requires a writable kernel.
Example fix
// before
await siyuan.storage.remove(path);
// after
try {
await siyuan.storage.remove(path);
} catch (e) {
if (String(e).includes('read-only mode')) {
// skip deletion silently or notify the user
} else {
throw e;
}
} Defensive patterns
Strategy: try-catch
Validate before calling
// Reuse the read-only probe from error 1012 and skip remove when readOnly is true.
Try / catch
try {
await siyuan.storage.remove(path);
} catch (e) {
if (/read-only mode/.test(String(e))) { /* skip deletion */ return; }
throw e;
} Prevention
- Detect read-only mode at startup and disable delete features.
- Do not queue deletions on publishing servers.
When it happens
Trigger: Calling storage.remove on a read-only kernel instance (published/preview server, demo environment, workspace mounted read-only). Every remove call rejects regardless of the target path.
Common situations: Plugin works on a normal kernel but is later deployed on a publishing server that runs read-only; user booted the kernel with a read-only flag for safety.
Related errors
- The current kernel is in read-only mode, storage.put is not
- failed to add storage path to watcher: %v
- failed to make directory: %w
- failed to write file: %w
- siyuan.storage: path traversal not allowed
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/7b4b032c92d84052.
Report an issue: GitHub.