siyuan-note/siyuan · error

injectClient: %v

Error message

injectClient: %v

What it means

injectClient registers the siyuan.server object (fetch, SSE, WebSocket helpers) into the plugin's goja runtime. The whole function is wrapped in a recover() deferred handler so that any panic during injection — e.g. lo.Must0 failing on a Set error, rt.NewObject/NewPromise failures, or a runtime in a broken state — is converted into this error with the panic value embedded. It surfaces as plugin-load failure rather than crashing the kernel.

Source

Thrown at kernel/plugin/api_client.go:42

	"net/http"
	"strings"
	"sync"
	"sync/atomic"

	"github.com/dop251/goja"
	"github.com/lxzan/gws"
	sse "github.com/r3labs/sse/v2"
	"github.com/samber/lo"
	"github.com/siyuan-note/logging"
	"github.com/siyuan-note/siyuan/kernel/model"
	"github.com/siyuan-note/siyuan/kernel/util"
)

// injectClient adds siyuan.server to the goja context.
func injectClient(p *KernelPlugin, rt *goja.Runtime, siyuan *goja.Object) (err error) {
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("injectClient: %v", r)
		}
	}()

	client := rt.NewObject()

	lo.Must0(client.Set("fetch", rt.ToValue(func(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
		promise, resolve, reject := rt.NewPromise()

		var argErr error
		var path string
		method := "GET"
		headers := map[string]string{}
		var bodyString *string
		var bodyBytes *[]byte

		if goja.IsString(call.Argument(0)) {
			path = call.Argument(0).String()
		} else {

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Check kernel logs for the full panic stack alongside the 'injectClient: %v' message
  2. Restart SiYuan and reload the plugin — the goja runtime is usually recreated fresh
  3. Disable recently installed/updated plugins to isolate one corrupting the runtime
  4. If reproducible, report with the panic value and plugin version; it is an internal-invariant failure, not a plugin API misuse
Defensive patterns

Strategy: try-catch

Try / catch

// plugin host side (Go): injectClient already recovers; log and fail plugin load gracefully
if err := injectClient(p, rt, siyuan); err != nil {
    logging.LogErrorf("[plugin:%s] injectClient failed: %v", p.Name, err)
    return err
}

Prevention

When it happens

Trigger: A panic occurs while building the client object: goja runtime is closed or exhausted, a client.Set call errors (propagated by lo.Must0), or an internal invariant in the client setup (e.g. resolving the kernel HTTP endpoint) panics.

Common situations: Plugin worker runtime torn down mid-injection; port/endpoint resolution failure inside the client closure triggering a panic during setup; a bug/regression in the plugin host rather than in plugin code.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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