siyuan-note/siyuan · warning
globalThis.siyuan.event is not an object
Error message
globalThis.siyuan.event is not an object
What it means
dispatchEvent calls ToObject on the resolved globalThis.siyuan.event value and throws this error when that conversion returns nil. It is a defensive check: the value survived the nil/undefined/null checks but could not be converted to a goja object, so the event handler cannot be looked up.
Source
Thrown at kernel/plugin/sandbox.go:347
}
}()
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 {
err = invokeErr
return
}
async = isJsPromise(invokeResult)
returnView on GitHub (pinned to 8641553a1f)
Solutions
- Inspect what is assigned to globalThis.siyuan.event and replace it with a plain JS object exposing a handler/on function
- When bridging Go values into the plugin runtime, wrap them with rt.ToValue / rt.NewObject instead of assigning raw host values
- Add a startup assertion in the plugin: if (typeof siyuan.event !== 'object') throw new Error('invalid siyuan.event')
Example fix
// before
siyuan.event = hostBridgeValue; // raw Go-backed value
// after
siyuan.event = { on: (name, cb) => hostBridgeSubscribe(name, cb) }; Defensive patterns
Strategy: type-guard
Validate before calling
if (!siyuan.event || typeof siyuan.event !== 'object' || typeof siyuan.event.on !== 'function') { throw new Error('siyuan.event must be a plain object with an on function'); } Type guard
const isEventObject = (v) => v != null && typeof v === 'object' && !Array.isArray(v);
Try / catch
if err := dispatchEvent(p, rt, e); err != nil { if strings.Contains(err.Error(), "not an object") { log.Errorf("plugin %s: bad siyuan.event value", p.Name) } return } Prevention
- Assign only plain JS objects to siyuan.event, never raw host/Go-bridged values
- Wrap bridged host functionality behind a plain object facade with function properties
- Assert the shape of siyuan.event in the plugin's startup code
When it happens
Trigger: globalThis.siyuan.event holds a non-object that defeats ToObject in this goja version — practically only reachable via unusual host values or exotic wrapped values assigned to siyuan.event.
Common situations: Plugin code assigning a host-provided non-JS value (e.g. a Go value bridged without conversion) to siyuan.event; goja version-specific export/bridge quirks.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- globalThis.siyuan.plugin.lifecycle is not an object
- path %v: expected object, got %T
- unsupported path type: %T
- globalThis.siyuan.event not found
- globalThis.siyuan.event is %s
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/589fe95c958caf6c.
Report an issue: GitHub.