{"record":{"id":"5fcbc450d623809b","repo":"siyuan-note/siyuan","slug":"injectplugin-v","errorCode":null,"errorMessage":"injectPlugin: %v","messagePattern":"injectPlugin: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/api_plugin.go","lineNumber":31,"sourceCode":"//\n// You should have received a copy of the GNU Affero General Public License\n// along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\npackage plugin\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/dop251/goja\"\n\t\"github.com/samber/lo\"\n\t\"github.com/siyuan-note/siyuan/kernel/bazaar\"\n)\n\n// injectPlugin adds siyuan.plugin to the goja context.\nfunc injectPlugin(p *KernelPlugin, rt *goja.Runtime, siyuan *goja.Object) (err error) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\terr = fmt.Errorf(\"injectPlugin: %v\", r)\n\t\t}\n\t}()\n\n\tlifecycle := rt.NewObject()\n\tlo.Must0(lifecycle.Set(\"onload\", goja.Null()))\n\tlo.Must0(lifecycle.Set(\"onrunning\", goja.Null()))\n\tlo.Must0(lifecycle.Set(\"onunload\", goja.Null()))\n\tlo.Must0(ObjectSeal(rt, lifecycle))\n\n\tplugin := rt.NewObject()\n\tlo.Must0(plugin.Set(\"name\", p.Name))\n\tlo.Must0(plugin.Set(\"version\", p.Version))\n\tlo.Must0(plugin.Set(\"displayName\", p.DisplayName))\n\tlo.Must0(plugin.Set(\"platform\", bazaar.GetCurrentBackend()))\n\tlo.Must0(plugin.Set(\"i18n\", p.I18n))\n\tlo.Must0(plugin.Set(\"lifecycle\", lifecycle))\n\tlo.Must0(ObjectFreeze(rt, plugin))\n","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/plugin/api_plugin.go#L13-L49","documentation":"injectPlugin sets up the siyuan.plugin object in the plugin's goja runtime. Any panic raised while creating/configuring the plugin namespace is recovered by the deferred func and converted into this error, so the plugin load aborts with a message that names the injection step.","triggerScenarios":"A panic occurs inside injectPlugin while building the lifecycle/objects for siyuan.plugin — e.g. a nil *goja.Object or a runtime panic during object Set calls, or a lo.Must0 assertion failing mid-setup.","commonSituations":"Kernel-side bug or incompatible goja runtime state during plugin bootstrap; typically seen when loading a plugin into a runtime that is being torn down or when internal invariants (non-nil siyuan object) are violated.","solutions":["Read the wrapped %v detail in the error message to identify the panicking operation","Verify the plugin's runtime is fully initialized before injectPlugin runs","Check plugin lifecycle defaults (onload/onrunning) are valid goja values","File/inspect kernel code at kernel/plugin/api_plugin.go if the panic reproduces deterministically"],"exampleFix":"// before: passing a nil siyuan object\ninjectPlugin(p, rt, nil)\n// after: guard before injection\nif siyuan == nil {\n    return fmt.Errorf(\"siyuan object not initialized\")\n}\ninjectPlugin(p, rt, siyuan)","handlingStrategy":"try-catch","validationCode":"if (!siyuan || typeof siyuan !== \"object\") {\n    throw new Error(\"siyuan namespace not initialized before plugin injection\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    await loadPlugin(plugin);\n} catch (e) {\n    if (String(e).startsWith(\"injectPlugin:\")) {\n        console.error(\"plugin namespace injection failed:\", e);\n    }\n}","preventionTips":["Keep the goja runtime healthy and fully initialized before injection","Do not pass nil/uninitialized objects into plugin setup","Check the %v detail in the message for the true cause"],"tags":["goja","plugin","panic-recovery","initialization"],"backgroundTag":"module-init-failed","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}