siyuan-note/siyuan · error

event.data is required

Error message

event.data is required

What it means

Panicked (converted to a Go error via rt.NewGoError) when the SSE port.send() receives an event object that has no data field (data is undefined). The SSE spec requires a data field for every event, so the kernel treats its absence as a hard error rather than silently dropping the event.

Source

Thrown at kernel/plugin/plugin.go:1384

		invokePortHook := func(name string, args ...goja.Value) {
			hook := port.Get(name)
			if fn, ok := goja.AssertFunction(hook); ok {
				if _, callErr := fn(port, args...); callErr != nil {
					logging.LogErrorf("[plugin:%s] sse server port hook %q: %v", p.Name, name, callErr)
				}
			}
		}

		port_send := rt.ToValue(func(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
			if eventJs := call.Argument(0); isJsValueNotNull(eventJs) {
				if eventObj := eventJs.ToObject(rt); eventObj != nil {
					e := sse.Event{}

					if data := eventObj.Get("data"); isJsValueNotUndefined(data) {
						e.Data = data.Export()
					} else {
						panic(rt.NewGoError(fmt.Errorf("event.data is required")))
					}

					if event := eventObj.Get("event"); goja.IsString(event) {
						e.Event = event.String()
					}

					if id := eventObj.Get("id"); goja.IsString(id) {
						e.Id = id.String()
					}

					if retry := eventObj.Get("retry"); goja.IsNumber(retry) {
						e.Retry = uint(retry.ToInteger())
					}

					events.In <- e
					return goja.Undefined()
				}
			}

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Always include data: port.send({ data: 'hello', event: 'ping' }).
  2. Default data to an empty string if you genuinely want an empty payload: port.send({ data: '' }).
  3. Validate the event object shape before calling send.

Example fix

// before
port.send({ event: name });

// after
port.send({ event: name, data: payload ?? '' });
Defensive patterns

Strategy: validation

Validate before calling

function hasData(e: any): boolean { return !!e && typeof e === 'object' && 'data' in e && e.data !== undefined; }

Type guard

function isSseEvent(e: unknown): e is { data: unknown; event?: string; id?: string; retry?: number } { return !!e && typeof e === 'object' && 'data' in (e as any) && (e as any).data !== undefined; }

Try / catch

try { port.send(event); } catch (e) { if (/event\.data is required/.test(String(e))) { port.send({ ...event, data: '' }); return; } throw e; }

Prevention

When it happens

Trigger: Plugin calls port.send({ event: 'ping' }) or port.send({}) without a data property; or data is set to undefined explicitly.

Common situations: Building an event object conditionally and forgetting to set data on a branch; sending a comment-style event without data.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/4f7384663d2bb0cc. Report an issue: GitHub.