siyuan-note/siyuan · error

injectPlugin: %v

Error message

injectPlugin: %v

What it means

injectPlugin sets up the siyuan.plugin object in the plugin's goja runtime. Any panic raised while creating/configuring the plugin namespace is recovered by the deferred func and converted into this error, so the plugin load aborts with a message that names the injection step.

Source

Thrown at kernel/plugin/api_plugin.go:31

//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

package plugin

import (
	"fmt"

	"github.com/dop251/goja"
	"github.com/samber/lo"
	"github.com/siyuan-note/siyuan/kernel/bazaar"
)

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

	lifecycle := rt.NewObject()
	lo.Must0(lifecycle.Set("onload", goja.Null()))
	lo.Must0(lifecycle.Set("onrunning", goja.Null()))
	lo.Must0(lifecycle.Set("onunload", goja.Null()))
	lo.Must0(ObjectSeal(rt, lifecycle))

	plugin := rt.NewObject()
	lo.Must0(plugin.Set("name", p.Name))
	lo.Must0(plugin.Set("version", p.Version))
	lo.Must0(plugin.Set("displayName", p.DisplayName))
	lo.Must0(plugin.Set("platform", bazaar.GetCurrentBackend()))
	lo.Must0(plugin.Set("i18n", p.I18n))
	lo.Must0(plugin.Set("lifecycle", lifecycle))
	lo.Must0(ObjectFreeze(rt, plugin))

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Read the wrapped %v detail in the error message to identify the panicking operation
  2. Verify the plugin's runtime is fully initialized before injectPlugin runs
  3. Check plugin lifecycle defaults (onload/onrunning) are valid goja values
  4. File/inspect kernel code at kernel/plugin/api_plugin.go if the panic reproduces deterministically

Example fix

// before: passing a nil siyuan object
injectPlugin(p, rt, nil)
// after: guard before injection
if siyuan == nil {
    return fmt.Errorf("siyuan object not initialized")
}
injectPlugin(p, rt, siyuan)
Defensive patterns

Strategy: try-catch

Validate before calling

if (!siyuan || typeof siyuan !== "object") {
    throw new Error("siyuan namespace not initialized before plugin injection");
}

Try / catch

try {
    await loadPlugin(plugin);
} catch (e) {
    if (String(e).startsWith("injectPlugin:")) {
        console.error("plugin namespace injection failed:", e);
    }
}

Prevention

When it happens

Trigger: A panic occurs inside injectPlugin while building the lifecycle/objects for siyuan.plugin — e.g. a nil *goja.Object or a runtime panic during object Set calls, or a lo.Must0 assertion failing mid-setup.

Common situations: Kernel-side bug or incompatible goja runtime state during plugin bootstrap; typically seen when loading a plugin into a runtime that is being torn down or when internal invariants (non-nil siyuan object) are violated.

Related errors


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