{"record":{"id":"a5fddff4d7f93b0f","repo":"siyuan-note/siyuan","slug":"panic-during-siyuan-storage-put-v","errorCode":null,"errorMessage":"panic during siyuan.storage.put: %v","messagePattern":"panic during siyuan\\.storage\\.put: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/api_storage.go","lineNumber":260,"sourceCode":"\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 {\n\t\t\t\t\t\t\t\tlogging.LogErrorf(\"[plugin:%s] siyuan.storage.put resolve: %v\", p.Name, resolveErr)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif rejectErr := reject(rt.NewGoError(err)); rejectErr != nil {\n\t\t\t\t\t\t\t\tlogging.LogErrorf(\"[plugin:%s] siyuan.storage.put reject: %v\", p.Name, rejectErr)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn\n\t\t\t\t\t}, nil)\n\t\t\t\t}()\n\n\t\t\t\tif mkdirErr := os.MkdirAll(filepath.Dir(abs), 0755); mkdirErr != nil {\n\t\t\t\t\terr = fmt.Errorf(\"failed to make directory: %w\", mkdirErr)","sourceCodeStart":242,"sourceCodeEnd":278,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/plugin/api_storage.go#L242-L278","documentation":"Thrown when a panic is recovered inside the goroutine that performs the file write for siyuan.storage.put(). The deferred recover() wraps the panic value into this message. It is a defensive boundary for unexpected runtime faults during directory creation or file writing, distinct from ordinary I/O errors which have their own messages (1014, 1015).","triggerScenarios":"A panic inside the write goroutine — e.g. nil dereference in filelock helpers, an assertion failure, or a runtime fault triggered by malformed path/content.","commonSituations":"Rare; indicates a kernel-level defect or an extreme edge case (corrupted state, concurrent teardown).","solutions":["Check the %v detail in the kernel log to locate the panic site.","Retry the put once with the same arguments to rule out a transient teardown race.","Report the panic with the path and content size if it reproduces.","Wrap put in try/catch and keep an in-memory copy as a fallback."],"exampleFix":"// before\nawait siyuan.storage.put(path, body);\n// after\ntry {\n  await siyuan.storage.put(path, body);\n} catch (e) {\n  console.error('storage.put panicked/failed', e);\n  memoryFallback.set(path, body);\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await siyuan.storage.put(path, body);\n} catch (e) {\n  if (/panic during siyuan.storage.put/.test(String(e))) {\n    memoryFallback.set(path, body);\n    return;\n  }\n  throw e;\n}","preventionTips":["Keep an in-memory copy of important state so a write panic does not lose data.","Avoid issuing writes during plugin teardown to dodge races."],"tags":["plugin-api","storage","panic","recovery","defensive"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}