{"record":{"id":"26f88552fca07ee6","repo":"siyuan-note/siyuan","slug":"the-current-kernel-is-in-read-only-mode-storage-p","errorCode":null,"errorMessage":"The current kernel is in read-only mode, storage.put is not allowed","messagePattern":"The current kernel is in read-only mode, storage\\.put is not allowed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/api_storage.go","lineNumber":247,"sourceCode":"\tlo.Must0(storage.Set(\"put\", rt.ToValue(func(call goja.FunctionCall, rt *goja.Runtime) goja.Value {\n\t\tpromise, resolve, reject := rt.NewPromise()\n\n\t\tvar argErr error\n\t\tvar path, content string\n\t\tif len(call.Arguments) < 2 {\n\t\t\targErr = fmt.Errorf(\"path and content required\")\n\t\t} else {\n\t\t\tpath = call.Argument(0).String()\n\t\t\tcontent = call.Argument(1).String()\n\t\t}\n\n\t\trunErr := p.worker.Run(func(rt *goja.Runtime) (result any, err error) {\n\t\t\tif argErr != nil {\n\t\t\t\terr = argErr\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif util.ReadOnly {\n\t\t\t\terr = fmt.Errorf(\"The current kernel is in read-only mode, storage.put is not allowed\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tabs, resolveErr := resolvePath(path)\n\t\t\tif resolveErr != nil {\n\t\t\t\terr = resolveErr\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tgo func() (result any, err error) {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\terr = fmt.Errorf(\"panic during siyuan.storage.put: %v\", r)\n\t\t\t\t\t}\n\n\t\t\t\t\tp.worker.Run(func(rt *goja.Runtime) (_ any, _ error) {\n\t\t\t\t\t\tif lo.IsNil(err) {\n\t\t\t\t\t\t\tif resolveErr := resolve(result); resolveErr != nil {","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/plugin/api_storage.go#L229-L265","documentation":"Thrown by siyuan.storage.put() when util.ReadOnly is true. The kernel can run in read-only mode (e.g. a published or preview instance where writes are forbidden); in that mode all storage mutations are rejected before any filesystem access. The check runs after argument validation but before path resolution and writing.","triggerScenarios":"Calling storage.put on a kernel started with the read-only flag, or on a hosted/published SiYuan instance that enforces util.ReadOnly. Any put call will reject regardless of path validity.","commonSituations":"Plugin developed against a normal desktop kernel is later loaded on a read-only publishing server; CI/demo environments booted read-only to prevent mutation; the user launched the kernel with a read-only workspace flag.","solutions":["Detect read-only mode at plugin startup and disable write features or switch to in-memory state.","Wrap put in try/catch and degrade gracefully when writes are rejected.","Surface a user-facing notice that the feature requires a writable kernel."],"exampleFix":"// before\nawait siyuan.storage.put('state.json', body);\n// after\ntry {\n  await siyuan.storage.put('state.json', body);\n} catch (e) {\n  if (String(e).includes('read-only mode')) {\n    notifyUser('This plugin needs a writable kernel.');\n  } else {\n    throw e;\n  }\n}","handlingStrategy":"try-catch","validationCode":"// Detect read-only mode once at startup by probing a write:\nlet readOnly = false;\ntry { await siyuan.storage.put('__probe', '1'); await siyuan.storage.remove('__probe'); }\ncatch (e) { readOnly = /read-only mode/.test(String(e)); }","typeGuard":null,"tryCatchPattern":"try {\n  await siyuan.storage.put(path, body);\n} catch (e) {\n  if (/read-only mode/.test(String(e))) {\n    notifyUser('Write features require a writable kernel.');\n    return;\n  }\n  throw e;\n}","preventionTips":["Probe writable mode at startup and disable write-only features up front.","Keep an in-memory fallback for state when running on publishing servers."],"tags":["plugin-api","storage","read-only","environment","permissions"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}