siyuan-note/siyuan · error
globalThis.siyuan.plugin.lifecycle not found
Error message
globalThis.siyuan.plugin.lifecycle not found
What it means
During hook invocation the kernel resolves the path globalThis.siyuan.plugin.lifecycle inside the plugin's goja runtime via getJsContextValue. If the value is undefined/null the runtime is told to run the hook anyway and fails fast with this error: the plugin never installed its lifecycle object, so no hooks can be dispatched.
Source
Thrown at kernel/plugin/plugin.go:866
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic during lifecycle hook invocation: %v", r)
}
if err != nil {
logging.LogErrorf("[plugin:%s] lifecycle hook [%q] error: %v", p.Name, name, err)
}
}()
done := make(chan TaskResult, 1)
runErr := p.worker.Run(func(rt *goja.Runtime) (_ any, err error) {
lifecycle, err := getJsContextValue(rt, []any{"siyuan", "plugin", "lifecycle"})
if err != nil {
return
}
if lifecycle == nil {
err = fmt.Errorf("globalThis.siyuan.plugin.lifecycle not found")
return
}
pluginObj := lifecycle.ToObject(rt)
if pluginObj == nil {
err = fmt.Errorf("globalThis.siyuan.plugin.lifecycle is not an object")
return
}
hookValue := pluginObj.Get(name)
hook, ok := goja.AssertFunction(hookValue)
if !ok {
err = fmt.Errorf("globalThis.siyuan.plugin.lifecycle.%s not bound to a function", name)
return
}
invokeFunction(func(_ *goja.Runtime, result *CallResult) {
done <- *result.TaskResult()View on GitHub (pinned to 8641553a1f)
Solutions
- Check earlier logs for JS load/compile errors from the plugin entry - fix the root script failure first
- Ensure the plugin assigns globalThis.siyuan.plugin.lifecycle (or registers via the official plugin scaffold) before hooks fire
- Reinstall/rebuild the plugin so its entry file is complete and compatible with the kernel API
- Verify the entry script actually ran: add a console log at the top of the plugin entry and check plugin logs
Example fix
// plugin entry (before)
export default class { onload() {} } // never attached to siyuan.plugin.lifecycle
// after
globalThis.siyuan = globalThis.siyuan || {}
globalThis.siyuan.plugin = globalThis.siyuan.plugin || {}
globalThis.siyuan.plugin.lifecycle = new (class { onload() {} onunload() {} })() Defensive patterns
Strategy: validation
Validate before calling
// plugin JS entry must end with something like:
if (!globalThis.siyuan?.plugin?.lifecycle) {
throw new Error('entry failed to install siyuan.plugin.lifecycle')
} Type guard
func lifecycleInstalled(rt *goja.Runtime) bool {
v, err := getJsContextValue(rt, []any{"siyuan", "plugin", "lifecycle"})
return err == nil && v != nil
} Try / catch
if err := dispatchHook("onload"); err != nil {
if strings.Contains(err.Error(), "lifecycle not found") {
logging.LogErrorf("plugin entry did not register lifecycle; disabling plugin")
// disable or quarantine the plugin
}
} Prevention
- Use the official plugin scaffold so globalThis.siyuan.plugin.lifecycle is always installed
- Check kernel logs for earlier entry-script compile errors - this error is usually downstream
- Verify the plugin entry file exists and is complete after install/update
- Add a self-check at the end of the plugin entry that asserts the lifecycle object
When it happens
Trigger: Calling invokeHook/lifecycle dispatch when the plugin's JS entry script did not (successfully) assign globalThis.siyuan.plugin.lifecycle - e.g. the script errored mid-execution or was never registered.
Common situations: A plugin entry file that failed to load earlier (syntax error, missing export) leaving the context unset; a plugin written for a different host (no `siyuan` global); truncated or corrupted plugin dist files.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- globalThis.siyuan.plugin.lifecycle.%s not bound to a functio
- panic during lifecycle hook invocation: %v
- globalThis.siyuan.plugin.lifecycle is not an object
- injectAgent: %v
- registerCapability requires 3 arguments: name, config, handl
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/cdbbffa033dc0de1.
Report an issue: GitHub.