{"record":{"id":"966e2083f869336a","repo":"siyuan-note/siyuan","slug":"globalthis-siyuan-server-s-s-is-not-an-object","errorCode":null,"errorMessage":"globalThis.siyuan.server[%s][%s] is not an object","messagePattern":"globalThis\\.siyuan\\.server\\[(.+?)\\]\\[(.+?)\\] is not an object","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/sandbox.go","lineNumber":504,"sourceCode":"\t\t}\n\t\treturn\n\t}\n\terr = fmt.Errorf(\"js value cannot be exported to a valid Go value\")\n\treturn\n}\n\n// getRequestHandler retrieves the handler function and its containing object for a given scope and request type from the plugin's JS context.\nfunc getRequestHandler(rt *goja.Runtime, scope AccessScope, requestType RequestType) (handler goja.Callable, handlerObj *goja.Object, err error) {\n\t// Get handler object: siyuan.server[scope][requestType]\n\thandlerObjValue, getObjErr := getJsContextValue(rt, []any{\"siyuan\", \"server\", string(scope), string(requestType)})\n\tif getObjErr != nil {\n\t\terr = getObjErr\n\t\treturn\n\t}\n\n\thandlerObj = handlerObjValue.ToObject(rt)\n\tif handlerObj == nil {\n\t\terr = fmt.Errorf(\"globalThis.siyuan.server[%s][%s] is not an object\", scope, requestType)\n\t\treturn\n\t}\n\n\t// Get handler: siyuan.server[scope][requestType].handler\n\thandlerValue := handlerObj.Get(\"handler\")\n\tif !isJsValueNotNull(handlerValue) {\n\t\terr = fmt.Errorf(\"siyuan.server[%s][%s].handler is not set\", scope, requestType)\n\t\treturn\n\t}\n\n\thandler, ok := goja.AssertFunction(handlerValue)\n\tif !ok {\n\t\terr = fmt.Errorf(\"siyuan.server[%s][%s].handler is not a function\", scope, requestType)\n\t\treturn\n\t}\n\n\treturn\n}","sourceCodeStart":486,"sourceCodeEnd":522,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/plugin/sandbox.go#L486-L522","documentation":"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.","triggerScenarios":"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.","commonSituations":"Typos in plugin registration code (assigning the handler function directly instead of { handler: fn }), or a plugin version whose export shape changed.","solutions":["Fix the plugin to register an object: siyuan.server[scope][requestType] = { handler: async (req) => ... }","Verify with console.log(typeof globalThis.siyuan.server[scope][requestType]) that it is 'object' and not null","Update the plugin to the version matching the current SiYuan plugin API"],"exampleFix":"// before\nsiyuan.server['plugin']['request'] = myHandler;\n// after\nsiyuan.server['plugin']['request'] = { handler: myHandler };","handlingStrategy":"validation","validationCode":"const node = globalThis.siyuan?.server?.[scope]?.[requestType]; if (typeof node !== 'object' || node === null) throw new Error(`siyuan.server[${scope}][${requestType}] must be an object`);","typeGuard":"function isHandlerNode(v) { return typeof v === 'object' && v !== null && typeof v.handler === 'function'; }","tryCatchPattern":"try { await request(scope, type); } catch (e) { if (String(e).includes('is not an object')) { reRegisterPluginHandlers(); } else { throw e; } }","preventionTips":["Register handlers as { handler: fn } objects, never bare values","Log typeof at registration time to catch shape mistakes early","Keep plugin registration code version-matched to the SiYuan plugin API"],"tags":["goja","plugin","registration","javascript-sandbox"],"backgroundTag":"type-mismatch","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}