siyuan-note/siyuan · error

globalThis.siyuan.event is %s

Error message

globalThis.siyuan.event is %s

What it means

dispatchEvent resolves globalThis.siyuan.event and rejects it when the value is JavaScript undefined or null, formatting the actual value into the message ('undefined' or 'null'). Unlike the 'not found' error (nil Go value), this means the property exists in the lookup sense but holds undefined/null at dispatch time.

Source

Thrown at kernel/plugin/sandbox.go:341

// dispatchEvent calls the globalThis.siyuan.event.on hook with the given event object.
func dispatchEvent(p *KernelPlugin, rt *goja.Runtime, e any) (async bool, err error) {
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("goja panic during dispatchEvent: %v", r)
		}
	}()

	event, err := getJsContextValue(rt, []any{"siyuan", "event"})
	if err != nil {
		return
	}
	if event == nil {
		err = fmt.Errorf("globalThis.siyuan.event not found")
		return
	}
	if goja.IsUndefined(event) || goja.IsNull(event) {
		err = fmt.Errorf("globalThis.siyuan.event is %s", event.String())
		return
	}

	eventObj := event.ToObject(rt)
	if eventObj == nil {
		err = fmt.Errorf("globalThis.siyuan.event is not an object")
		return
	}

	handlerValue := eventObj.Get("handler")
	handler, ok := goja.AssertFunction(handlerValue)
	if !ok {
		return
	}

	eventJs := rt.ToValue(e)
	invokeResult, invokeErr := handler(event, eventJs)
	if invokeErr != nil {

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Find and remove the assignment that sets siyuan.event to undefined/null in the plugin
  2. Guard initialization so siyuan.event is always an object with a callable handler before the plugin reports readiness
  3. If the plugin unloads, ensure it also stops receiving kernel events so dispatchEvent is not called against a torn-down context

Example fix

// before
siyuan.event = pluginModule && pluginModule.event; // undefined when pluginModule fails to load
// after
if (pluginModule && pluginModule.event) { siyuan.event = pluginModule.event; }
Defensive patterns

Strategy: validation

Validate before calling

if (siyuan.event === undefined || siyuan.event === null) { siyuan.event = createEventBus(); }

Type guard

const isValidEventBus = (e) => e != null && typeof e === 'object' && typeof e.on === 'function';

Try / catch

if err := dispatchEvent(p, rt, e); err != nil { if strings.Contains(err.Error(), "is undefined") || strings.Contains(err.Error(), "is null") { reinitEventShim(rt) } }

Prevention

When it happens

Trigger: Plugin code assigns siyuan.event = undefined or null (explicitly or via a failed destructure/default), then the kernel dispatches an event through dispatchEvent.

Common situations: Teardown code clearing plugin state; a conditional init like `siyuan.event = someModule?.event` where someModule is undefined; plugin reload racing with event dispatch.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/3cfe03cbae9991c0. Report an issue: GitHub.