{"record":{"id":"ad1826c7c9be1b81","repo":"siyuan-note/siyuan","slug":"siyuan-server-s-s-handler-is-not-set","errorCode":null,"errorMessage":"siyuan.server[%s][%s].handler is not set","messagePattern":"siyuan\\.server\\[(.+?)\\]\\[(.+?)\\]\\.handler is not set","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/sandbox.go","lineNumber":511,"sourceCode":"// 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}\n\n// requestGoToJs converts a Go Request to a JavaScript value.\nfunc requestGoToJs(p *KernelPlugin, rt *goja.Runtime, request *Request) (jsRequest goja.Value, err error) {\n\t// convert body raw data to js object\n\tif data, ok := request.Request.Body.Data.(*[]byte); ok && data != nil {\n\t\trequest.Request.Body.Data, err = NewDataObject(p, rt, *data)\n\t\tif err != nil {","sourceCodeStart":493,"sourceCodeEnd":529,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/plugin/sandbox.go#L493-L529","documentation":"Thrown by getRequestHandler when globalThis.siyuan.server[scope][requestType] exists as an object but has no `handler` property that isJsValueNotNull — the registration object is present but the handler callable is missing. The plugin registered a scope/requestType entry without assigning .handler.","triggerScenarios":"Plugin sets globalThis.siyuan.server.network.beforeRequest = { priority: 1 } (or {}) but omits the `handler` field; or sets handler to undefined/null explicitly.","commonSituations":"Plugin author added metadata fields (priority, label) but forgot handler; partial/typo registration; copied a sample and dropped the handler line.","solutions":["Add a callable `handler` to the registration object: { handler: fn }.","Confirm handler is a function and not undefined/null (isJsValueNotNull must pass).","Match the scope/requestType string keys to the kernel's AccessScope/RequestType constants."],"exampleFix":"// before\nglobalThis.siyuan.server.network.beforeRequest = { priority: 10 }\n// after\nglobalThis.siyuan.server.network.beforeRequest = { priority: 10, handler: (req) => { /*...*/ } }","handlingStrategy":"validation","validationCode":"// Plugin side: assert handler present before registration completes.\nfunction registerHandler(scope: string, rt: string, fn: Function): void {\n  const entry = { handler: fn }\n  if (typeof entry.handler !== 'function') throw new Error('handler missing')\n  globalThis.siyuan.server[scope][rt] = entry\n}","typeGuard":"function hasHandler(v: unknown): v is { handler: Function } {\n  return !!v && typeof v === 'object' && typeof (v as any).handler === 'function'\n}","tryCatchPattern":null,"preventionTips":["Always include a callable handler in the registration object.","Use a single registration helper to enforce the shape.","Unit-test plugin registration against the kernel's expected object layout."],"tags":["plugin","goja","javascript-runtime","server-hooks","missing-handler"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}