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
- Find and remove the assignment that sets siyuan.event to undefined/null in the plugin
- Guard initialization so siyuan.event is always an object with a callable handler before the plugin reports readiness
- 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
- Never assign undefined/null to siyuan.event; only replace it with another valid event bus
- Guard optional-chaining assignments that may yield undefined
- On plugin unload, unregister listeners instead of nulling siyuan.event
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
- globalThis.siyuan.event not found
- path %v: value is %s
- goja panic during dispatchEvent: %v
- globalThis.siyuan.event is not an object
- synchronous function returned a Promise
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/3cfe03cbae9991c0.
Report an issue: GitHub.