{"record":{"id":"7eabcba307670e64","repo":"siyuan-note/siyuan","slug":"subscribe-plugin-events-v","errorCode":null,"errorMessage":"subscribe plugin events: %v","messagePattern":"subscribe plugin events: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/plugin.go","lineNumber":278,"sourceCode":"\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 {\n\t\treturn fmt.Errorf(\"subscribe plugin events: %v\", subscribeErr)\n\t}\n\n\tp.onLoad()\n\tp.updateState(PluginStateRunning)\n\tp.onRunning()\n\n\tp.bus.Publish(EventBusTopicRuntime, createEventMessage(\"start\", nil))\n\n\tlogging.LogDebugf(\"[plugin:%s] started\", p.Name)\n\treturn\n}\n\n// stop cleanly shuts down the plugin: closes sockets, frees goja runtime.\nfunc (p *KernelPlugin) stop() (ok bool, err error) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tp.error()\n\t\t\tok = false","sourceCodeStart":260,"sourceCodeEnd":296,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/plugin/plugin.go#L260-L296","documentation":"Wraps a failure from `subscribeEventHandlers()` during plugin start in `KernelPlugin.start()`. The kernel first initializes the goja runtime, then registers the plugin's event handlers; if that registration step fails, the start sequence aborts with this prefixed error and the plugin never reaches PluginStateRunning (onLoad/updateState/onRunning are skipped).","triggerScenarios":"Calling StartPlugin when p.subscribeEventHandlers() returns an error - e.g. the plugin's JS event registration throws, or the internal event bus registration fails before onLoad runs.","commonSituations":"A plugin whose entry script registers handlers against an incompatible plugin API version; a plugin that throws during its subscribe path; kernel event bus not yet initialized when the plugin starts.","solutions":["Read the wrapped %v detail in the log to find the underlying subscribeEventHandlers failure","Fix the plugin's event-registration code so it does not throw (check API surface against the current kernel version)","Check kernel logs for prior errors from the event bus; ensure the kernel finished bootstrapping before StartPlugin","Update or reinstall the plugin to a version compatible with the running SiYuan kernel"],"exampleFix":"// plugin JS side (before)\nonExternalRegister(() => loadPlugin(getWidgetID()))  // typo'd API, throws during subscribe\n// after\nif (typeof onExternalRegister === 'function') {\n  onExternalRegister(() => loadPlugin(getWidgetID()))\n}","handlingStrategy":"try-catch","validationCode":"if plugin.State() != PluginStateStopped {\n  return fmt.Errorf(\"plugin %s not in startable state\", plugin.Name)\n}","typeGuard":null,"tryCatchPattern":"if err := StartPlugin(p); err != nil {\n  if strings.Contains(err.Error(), \"subscribe plugin events\") {\n    logging.LogErrorf(\"plugin %s event subscribe failed: %v\", p.Name, err)\n    // fall back: start without event handlers or disable plugin\n  }\n}","preventionTips":["Keep plugin event-registration code defensive (feature-detect kernel APIs before subscribing)","Pin plugin API compatibility with the kernel version you target","Test plugin start/stop cycles in CI against the current kernel","Log the wrapped inner error, not just the wrapper, when debugging"],"tags":["plugin","lifecycle","event-subscription"],"backgroundTag":"plugin-startup-failed","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"}