siyuan-note/siyuan · error
subscribe plugin events: %v
Error message
subscribe plugin events: %v
What it means
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).
Source
Thrown at kernel/plugin/plugin.go:278
}
if err != nil {
p.error()
}
}()
p.updateState(PluginStateLoading)
baseDir := filepath.Join(util.DataDir, "storage", "petal", p.Name)
if err := os.MkdirAll(baseDir, 0755); err != nil {
return fmt.Errorf("create plugin dir [%s] failed: %s", baseDir, err)
}
if runtimeErr := p.InitRuntime(); runtimeErr != nil {
return fmt.Errorf("start runtime: %v", runtimeErr)
}
if subscribeErr := p.subscribeEventHandlers(); subscribeErr != nil {
return fmt.Errorf("subscribe plugin events: %v", subscribeErr)
}
p.onLoad()
p.updateState(PluginStateRunning)
p.onRunning()
p.bus.Publish(EventBusTopicRuntime, createEventMessage("start", nil))
logging.LogDebugf("[plugin:%s] started", p.Name)
return
}
// stop cleanly shuts down the plugin: closes sockets, frees goja runtime.
func (p *KernelPlugin) stop() (ok bool, err error) {
defer func() {
if r := recover(); r != nil {
p.error()
ok = falseView on GitHub (pinned to 8641553a1f)
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
Example fix
// plugin JS side (before)
onExternalRegister(() => loadPlugin(getWidgetID())) // typo'd API, throws during subscribe
// after
if (typeof onExternalRegister === 'function') {
onExternalRegister(() => loadPlugin(getWidgetID()))
} Defensive patterns
Strategy: try-catch
Validate before calling
if plugin.State() != PluginStateStopped {
return fmt.Errorf("plugin %s not in startable state", plugin.Name)
} Try / catch
if err := StartPlugin(p); err != nil {
if strings.Contains(err.Error(), "subscribe plugin events") {
logging.LogErrorf("plugin %s event subscribe failed: %v", p.Name, err)
// fall back: start without event handlers or disable plugin
}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- panic during plugin stop: %v
- plugin stopped: %w
- panic during lifecycle hook invocation: %v
- globalThis.siyuan.plugin.lifecycle not found
- globalThis.siyuan.plugin.lifecycle is not an object
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/7eabcba307670e64.
Report an issue: GitHub.