siyuan-note/siyuan · error

panic during siyuan.client.event: %v

Error message

panic during siyuan.client.event: %v

What it means

A panic was recovered inside the SSE subscription goroutine of siyuan.client.event. The %v is the recovered value. This is an internal runtime failure during the SSE read loop, not a caller argument error (those are caught before the goroutine starts).

Source

Thrown at kernel/plugin/api_client.go:697

			lo.Must0(esObj.Set("readyState", rt.ToValue(readyState.Load())))
			lo.Must0(esObj.Set("url", rt.ToValue(path)))

			lo.Must0(esObj.Set("onopen", goja.Null()))
			lo.Must0(esObj.Set("onmessage", goja.Null()))
			lo.Must0(esObj.Set("onclose", goja.Null()))
			lo.Must0(esObj.Set("onerror", goja.Null()))

			lo.Must0(esObj.Set("close", es_close))

			lo.Must0(ObjectSeal(rt, esObj))

			setReadyState(EventSourceConnecting)

			go func() {
				var err error
				defer func() {
					if r := recover(); r != nil {
						err = fmt.Errorf("panic during siyuan.client.event: %v", r)
					}

					doClose()

					p.worker.Run(func(rt *goja.Runtime) (_ any, _ error) {
						if err != nil && !errors.Is(err, context.Canceled) {
							event := rt.NewObject()
							event.Set("type", rt.ToValue("error"))
							event.Set("error", rt.NewGoError(err))
							invokeEsHook("onerror", event)
						}
						if EventSourceState(readyState.Load()) != EventSourceClosed {
							setReadyState(EventSourceClosed)
						}
						return
					}, nil)
				}()

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Check the kernel log for the recovered panic and report it with the plugin name.
  2. Ensure the plugin is not unloaded while the EventSource is open (call es.close() first).
  3. Update kernel/plugin runtime to the latest version.

Example fix

const es = await siyuan.client.event('/events/foo');
es.onerror = (e) => {
  if (String(e.error).includes('panic during')) {
    // internal failure; optionally recreate the EventSource
  }
};
Defensive patterns

Strategy: try-catch

Try / catch

es.onerror = (ev) => {
  const msg = String(ev?.error ?? '');
  if (msg.includes('panic during')) { /* log; optionally reconnect via new event() */ }
};

Prevention

When it happens

Trigger: A bug in the SSE client, the goja runtime, or a race during plugin unload while subscribed. The recover in the goroutine's defer converts the panic into an onerror event.

Common situations: Plugin hot-reload or kernel shutdown during an active SSE stream, or a version-specific bug in the SSE library.

Related errors


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