{"record":{"id":"ee1f5ef2b575cd2a","repo":"siyuan-note/siyuan","slug":"second-argument-must-be-a-config-object","errorCode":null,"errorMessage":"second argument must be a config object","messagePattern":"second argument must be a config object","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/api_agent.go","lineNumber":125,"sourceCode":"\t\t\t\t\t\t}\n\t\t\t\t\t\tif outputSchemaValue := configObj.Get(\"outputSchema\"); isJsValueNotNull(outputSchemaValue) {\n\t\t\t\t\t\t\tif outputSchema, err = jsCapabilitySchemaToGoSchema(rt, outputSchemaValue); err != nil {\n\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif effectsValue := configObj.Get(\"effects\"); isJsValueNotNull(effectsValue) {\n\t\t\t\t\t\t\tif effects, err = jsCapabilityEffectsToGoEffects(rt, effectsValue); err != nil {\n\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif actionEffectsValue := configObj.Get(\"actionEffects\"); isJsValueNotNull(actionEffectsValue) {\n\t\t\t\t\t\t\tif actionEffects, err = jsCapabilityActionEffectsToGoEffects(rt, actionEffectsValue); err != nil {\n\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\terr = fmt.Errorf(\"second argument must be a config object\")\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif fn, ok := goja.AssertFunction(call.Argument(2)); ok {\n\t\t\t\t\thandler = fn\n\t\t\t\t} else {\n\t\t\t\t\terr = fmt.Errorf(\"third argument must be a handler function\")\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t}()\n\n\t\trunErr := p.worker.Run(func(rt *goja.Runtime) (result any, err error) {\n\t\t\tif argErr != nil {\n\t\t\t\terr = argErr\n\t\t\t\treturn\n\t\t\t}\n","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/plugin/api_agent.go#L107-L143","documentation":"The second argument to registerCapability() was not usable as a config object (it was a non-object value such as a string, number, boolean, or null). The runtime calls ToObject on argument 1 and rejects the call when it is not a usable object, because all capability metadata (description, schemas) is read from it.","triggerScenarios":"registerCapability(name, \"description string\", handler); registerCapability(name, null, handler); or passing the handler as the second argument with only two arguments total.","commonSituations":"Passing a JSON string instead of a parsed object; argument order mistakes when the handler is placed second; a config variable that failed to load and is null/undefined.","solutions":["Pass a plain object literal as the second argument: { description, inputSchema, ... }","Parse JSON strings into objects before passing (JSON.parse)","Check that the config variable is defined and typeof === \"object\""],"exampleFix":"// before\nplugin.registerCapability(\"search\", JSON.stringify(config), handler);\n// after\nplugin.registerCapability(\"search\", config, handler);","handlingStrategy":"type-guard","validationCode":"if (config === null || typeof config !== \"object\" || Array.isArray(config)) { throw new TypeError(\"config must be a plain object\"); }","typeGuard":"const isConfigObject = (v) => v != null && typeof v === \"object\" && !Array.isArray(v);","tryCatchPattern":"try { plugin.registerCapability(name, config, handler); } catch (e) { if (String(e).includes(\"second argument must be a config object\")) { throw new TypeError(\"Pass a plain object as the 2nd argument, not \" + typeof config); } throw e; }","preventionTips":["Pass object literals, not JSON strings — parse JSON first","Do not pass the handler as the second argument","Check config-loading code for null results"],"tags":["plugin-api","type-error","config-object"],"backgroundTag":"invalid-argument-value","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"}