siyuan-note/siyuan · error

globalThis.siyuan.server

Error message

globalThis.siyuan.server[%s][%s] is not an object

What it means

getRequestHandler walks the plugin's JS context globalThis.siyuan.server[scope][requestType] and converts the found value to a *goja.Object. If the property exists but ToObject yields nil (the value cannot be treated as an object), this error reports that the expected handler container is not an object.

Solutions

  1. Fix the plugin to register an object: siyuan.server[scope][requestType] = { handler: async (req) => ... }
  2. Verify with console.log(typeof globalThis.siyuan.server[scope][requestType]) that it is 'object' and not null
  3. Update the plugin to the version matching the current SiYuan plugin API

Example fix

// before
siyuan.server['plugin']['request'] = myHandler;
// after
siyuan.server['plugin']['request'] = { handler: myHandler };
Defensive patterns

Strategy: validation

Validate before calling

const node = globalThis.siyuan?.server?.[scope]?.[requestType]; if (typeof node !== 'object' || node === null) throw new Error(`siyuan.server[${scope}][${requestType}] must be an object`);

Type guard

function isHandlerNode(v) { return typeof v === 'object' && v !== null && typeof v.handler === 'function'; }

Try / catch

try { await request(scope, type); } catch (e) { if (String(e).includes('is not an object')) { reRegisterPluginHandlers(); } else { throw e; } }

Prevention

When it happens

Trigger: A plugin defines siyuan.server[scope][requestType] as a non-object value (string, number, function, boolean) instead of an object with a .handler member, when the sandbox resolves a registered request handler.

Common situations: Typos in plugin registration code (assigning the handler function directly instead of { handler: fn }), or a plugin version whose export shape changed.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/966e2083f869336a. Report an issue: GitHub.

Appendix: source

Thrown at kernel/plugin/sandbox.go:504

		}
		return
	}
	err = fmt.Errorf("js value cannot be exported to a valid Go value")
	return
}

// getRequestHandler retrieves the handler function and its containing object for a given scope and request type from the plugin's JS context.
func getRequestHandler(rt *goja.Runtime, scope AccessScope, requestType RequestType) (handler goja.Callable, handlerObj *goja.Object, err error) {
	// Get handler object: siyuan.server[scope][requestType]
	handlerObjValue, getObjErr := getJsContextValue(rt, []any{"siyuan", "server", string(scope), string(requestType)})
	if getObjErr != nil {
		err = getObjErr
		return
	}

	handlerObj = handlerObjValue.ToObject(rt)
	if handlerObj == nil {
		err = fmt.Errorf("globalThis.siyuan.server[%s][%s] is not an object", scope, requestType)
		return
	}

	// Get handler: siyuan.server[scope][requestType].handler
	handlerValue := handlerObj.Get("handler")
	if !isJsValueNotNull(handlerValue) {
		err = fmt.Errorf("siyuan.server[%s][%s].handler is not set", scope, requestType)
		return
	}

	handler, ok := goja.AssertFunction(handlerValue)
	if !ok {
		err = fmt.Errorf("siyuan.server[%s][%s].handler is not a function", scope, requestType)
		return
	}

	return
}

View on GitHub (pinned to 9f775e8a12)