{"record":{"id":"339a01d509881055","repo":"siyuan-note/siyuan","slug":"goja-panic-during-start-v","errorCode":null,"errorMessage":"goja panic during start: %v","messagePattern":"goja panic during start: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"kernel/plugin/plugin.go","lineNumber":259,"sourceCode":"func (p *KernelPlugin) error() {\n\tif p.cancel != nil {\n\t\tp.cancel()\n\t}\n\tp.closeStorageWatcher()\n\tp.Clear()\n\n\tif err := p.close(); err != nil {\n\t\tlogging.LogErrorf(\"[plugin:%s] failed to close runtime during error handling: %v\", p.Name, err)\n\t}\n\n\tp.updateState(PluginStateError)\n}\n\n// start creates the goja runtime, injects sandbox globals, and evaluates kernel.js.\nfunc (p *KernelPlugin) start() (err error) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\terr = fmt.Errorf(\"goja panic during start: %v\", r)\n\t\t}\n\t\tif err != nil {\n\t\t\tp.error()\n\t\t}\n\t}()\n\n\tp.updateState(PluginStateLoading)\n\n\tbaseDir := filepath.Join(util.DataDir, \"storage\", \"petal\", p.Name)\n\tif err := os.MkdirAll(baseDir, 0755); err != nil {\n\t\treturn fmt.Errorf(\"create plugin dir [%s] failed: %s\", baseDir, err)\n\t}\n\n\tif runtimeErr := p.InitRuntime(); runtimeErr != nil {\n\t\treturn fmt.Errorf(\"start runtime: %v\", runtimeErr)\n\t}\n\n\tif subscribeErr := p.subscribeEventHandlers(); subscribeErr != nil {","sourceCodeStart":241,"sourceCodeEnd":277,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/plugin/plugin.go#L241-L277","documentation":"`KernelPlugin.start` wraps its whole body in a recover; any Go panic during plugin startup (state updates, directory creation, runtime init, event subscription, load callbacks) is converted to `goja panic during start: %v`, the plugin is moved to PluginStateError, and its runtime/capabilities are cleaned up. This is the outermost safety net for the plugin boot sequence.","triggerScenarios":"A panic anywhere in start() — e.g. inside p.onLoad()/onRunning() callbacks that invoke plugin JS, or during PushKernelPluginState — before the more specific wrapped errors (1698/1699) are produced.","commonSituations":"A plugin's load hook throwing a Go-level panic in goja, nil pointers in state publishing after kernel upgrade, or concurrent StartPlugin calls on the same plugin instance.","solutions":["Read the panic value to locate the failing startup step","Check plugin log output immediately before the panic for the actual JS/Go failure","Disable the problematic plugin to restore stability, then update or reinstall it","Report with plugin name and full panic message if reproducible"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := StartPlugin(p); err != nil { log.Errorf(\"plugin %s failed to start: %v\", p.Name, err); /* plugin is already in error state; skip it */ }","preventionTips":["Guard plugin load hooks (onLoad/onRunning) against throwing","Start plugins serially, not concurrently","Keep kernel state-publish code nil-safe across upgrades","Disable a crashing plugin first, then debug it"],"tags":["goja","panic-recovery","plugin-lifecycle","startup"],"backgroundTag":"internal-invariant-violation","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}