siyuan-note/siyuan · error

task executor panicked: %v

Error message

task executor panicked: %v

What it means

Worker.Run wraps task execution on the JS event loop with a recover() so a panic inside a TaskExecutor doesn't crash the kernel. When a panic is caught, the original stack is logged and the task fails with this wrapped error, which is then delivered to the TaskCallback. The message includes the panic value; the real stack is in the kernel log.

Source

Thrown at kernel/plugin/worker.go:64

		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)
			}
			if callback != nil {
				callback(rt, result, err)
			}
		}()

		result, err = executor(rt)
	})
	if !success {
		return fmt.Errorf("failed to run task on event loop")
	}
	return nil
}

func (w *Worker) RunSync(fn TaskExecutor) (result any, err error) {
	response := make(chan TaskResult, 1)
	err = w.Run(fn, func(rt *goja.Runtime, result any, err error) {
		response <- TaskResult{result, err}

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Read the full stack trace logged by logging.LogErrorf alongside 'task executor panicked' to locate the panicking line.
  2. Fix the underlying panic in the TaskExecutor (nil check, safe type assertion with ok, bounds check).
  3. Handle the error in the TaskCallback so callers receive a proper failure instead of hanging.
  4. Replace unchecked type assertions in the executor with the comma-ok form to convert panics into errors.

Example fix

// before
v := arg.(*MyType)
// after
v, ok := arg.(*MyType)
if !ok {
    err = fmt.Errorf("unexpected argument type %T", arg)
    return
}
Defensive patterns

Strategy: try-catch

Try / catch

func(rt *goja.Runtime) {
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("task executor panicked: %v", r)
        }
    }()
    // executor body
}

Prevention

When it happens

Trigger: Any TaskExecutor passed to worker.Run panics — e.g. nil pointer dereference, index out of range, or a type assertion failure while building JS arguments or processing results on the goja runtime.

Common situations: A plugin returns data in an unexpected shape and the executor's type assertion (`x.(*SomeType)`) panics; a nil map/slice access in the executor; a bug introduced by a kernel update in argument conversion code.

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/b40fc382cdb01412. Report an issue: GitHub.