siyuan-note/siyuan · error
worker event loop not initialized
Error message
worker event loop not initialized
What it means
Worker.Run executes a task on the goja event loop previously injected via Worker.Start(loop). If Run is called before Start, w.loop is nil and the worker cannot schedule onto the runtime, so it returns this error. It is an initialization-order bug in the worker's lifecycle.
Source
Thrown at kernel/plugin/worker.go:46
type TaskExecutor func(rt *goja.Runtime) (result any, err error)
type TaskCallback func(rt *goja.Runtime, result any, err error)
type Worker struct {
loop *eventloop.EventLoop
}
type TaskResult struct {
value any
err error
}
func (w *Worker) Start(loop *eventloop.EventLoop) {
w.loop = loop
}
func (w *Worker) Run(executor TaskExecutor, callback TaskCallback) error {
if w.loop == nil {
return fmt.Errorf("worker event loop not initialized")
}
success := w.loop.RunOnLoop(func(rt *goja.Runtime) {
var result any
var err error
defer func() {
defer func() {
// 捕获回调中的 panic 并保留原始调用栈,便于定位 Promise 处理异常。
if r := recover(); r != nil {
logging.LogErrorf("task callback panicked: %v\n%s", r, debug.Stack())
}
}()
// 捕获执行器中的 panic 并保留原始调用栈,同时将错误传给回调。
if r := recover(); r != nil {
logging.LogErrorf("task executor panicked: %v\n%s", r, debug.Stack())
err = fmt.Errorf("task executor panicked: %v", r)View on GitHub (pinned to 8641553a1f)
Solutions
- Call worker.Start(loop) with the plugin's eventloop.EventLoop before the first worker.Run call.
- Check plugin initialization order — ensure the JS runtime/eventloop bootstraps before any capability/hook/RPC dispatch.
- If the loop may legitimately be absent (plugin unloaded), check errors.Is/inspect the returned error and queue or reject the task gracefully.
- Audit teardown/reload paths so a Worker is re-Started with the new loop after a plugin reload.
Example fix
// before w.Run(executor, cb) // loop never set // after w.Start(loop) w.Run(executor, cb)
Defensive patterns
Strategy: try-catch
Validate before calling
// Go: ensure the loop is set before scheduling
if w.loop == nil {
return fmt.Errorf("worker event loop not initialized")
} Try / catch
if err := w.Run(executor, callback); err != nil {
// loop missing: initialize via w.Start(loop) and retry, or fail the task cleanly
} Prevention
- Always call Worker.Start(loop) immediately after constructing the worker.
- Re-Start the worker with the new loop after plugin reload/unload cycles.
- Assert loop initialization in plugin boot tests.
When it happens
Trigger: Calling worker.Run(executor, callback) without having called worker.Start(eventLoop) first; the runtime/eventloop was torn down (e.g. plugin unloaded) and the loop reference cleared or never set on a recreated Worker; two Worker instances created but Start called on the wrong one.
Common situations: Kernel code invoking agent capabilities, hooks, or RPC after plugin shutdown but before the worker is re-initialized; refactoring moved Start after the first Run; a nil loop leaked from a failed plugin boot.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/4b8c7bfdefb30160.
Report an issue: GitHub.