{"record":{"id":"2c45fd2c5c8f8ac0","repo":"siyuan-note/siyuan","slug":"failed-to-run-task-on-event-loop","errorCode":null,"errorMessage":"failed to run task on event loop","messagePattern":"failed to run task on event loop","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/worker.go","lineNumber":74,"sourceCode":"\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tlogging.LogErrorf(\"task callback panicked: %v\\n%s\", r, debug.Stack())\n\t\t\t\t}\n\t\t\t}()\n\n\t\t\t// 捕获执行器中的 panic 并保留原始调用栈，同时将错误传给回调。\n\t\t\tif r := recover(); r != nil {\n\t\t\t\tlogging.LogErrorf(\"task executor panicked: %v\\n%s\", r, debug.Stack())\n\t\t\t\terr = fmt.Errorf(\"task executor panicked: %v\", r)\n\t\t\t}\n\t\t\tif callback != nil {\n\t\t\t\tcallback(rt, result, err)\n\t\t\t}\n\t\t}()\n\n\t\tresult, err = executor(rt)\n\t})\n\tif !success {\n\t\treturn fmt.Errorf(\"failed to run task on event loop\")\n\t}\n\treturn nil\n}\n\nfunc (w *Worker) RunSync(fn TaskExecutor) (result any, err error) {\n\tresponse := make(chan TaskResult, 1)\n\terr = w.Run(fn, func(rt *goja.Runtime, result any, err error) {\n\t\tresponse <- TaskResult{result, err}\n\t})\n\n\tif err != nil {\n\t\tclose(response)\n\t\treturn\n\t}\n\n\tr := <-response\n\tresult = r.value\n\terr = r.err","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/plugin/worker.go#L56-L92","documentation":"The plugin Worker schedules a task (TaskExecutor) on a JS event loop (e.g. a GJavaScript/v8-style loop for plugin runtime). After running the callback, the deferred result is checked; if the executor set a non-nil error, Run() collapses it into the generic sentinel \"failed to run task on event loop\". It means the task itself failed while executing inside the event loop, not that the loop could not be reached.","triggerScenarios":"Calling Worker.Run(executor) where the executor function returns a non-nil error (success flag false after `result, err = executor(rt)` in kernel/plugin/worker.go:74). Callers include invokeAgentCapability, invokeHook, callRpcMethod, runtimeEventHandler and the HTTP handler path.","commonSituations":"A plugin hook or agent capability panics or returns an error inside the JS runtime; a runtime (rt) is in a bad state (closed loop, missing bindings); RPC method invoked on a plugin whose runtime threw while handling the call.","solutions":["Inspect kernel/plugin logs just before this error for the underlying error the executor produced; the generic message discards the original cause, so check the plugin's own console/log output","Verify the plugin runtime was fully initialized (runtime loaded, entry script executed) before invoking Run","If you wrote the hook/capability, fix the error it returns (nil check all runtime API results)","If the executor needs the original error surfaced, change Run/TaskExecutor plumbing to wrap `err` (e.g. fmt.Errorf(\"failed to run task on event loop: %w\", err)) instead of dropping it"],"exampleFix":"// before\nif !success {\n\treturn fmt.Errorf(\"failed to run task on event loop\")\n}\n// after\nif !success {\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to run task on event loop: %w\", err)\n\t}\n\treturn fmt.Errorf(\"failed to run task on event loop\")\n}","handlingStrategy":"try-catch","validationCode":"// Go: check runtime readiness before dispatch\nif w.runtime == nil || w.closed() {\n\treturn errors.New(\"plugin runtime not ready\")\n}","typeGuard":"func (w *Worker) ready() bool { return w != nil && w.loop != nil }","tryCatchPattern":"if err := worker.Run(executor); err != nil {\n\tif strings.Contains(err.Error(), \"failed to run task on event loop\") {\n\t\t// fall back to sync path or log plugin-side error\n\t}\n}","preventionTips":["Always initialize the plugin runtime before calling Run","Have executors return wrapped, descriptive errors instead of bare failures","Wrap err in the worker rather than discarding the cause","Log plugin-side exceptions to correlate with this generic message"],"tags":["plugin-runtime","event-loop","task-execution","go"],"backgroundTag":"event-loop-task-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"}