siyuan-note/siyuan · error

second argument must be a config object

Error message

second argument must be a config object

What it means

Thrown by siyuan.agent.registerCapability when the second argument (config) fails isJsValueNotNull — meaning it is null, undefined, or goja's representation of absent. The function needs a config object to extract description, inputSchema, and optional fields; a null config makes all of those inaccessible.

Source

Thrown at kernel/plugin/api_agent.go:125

						}
						if outputSchemaValue := configObj.Get("outputSchema"); isJsValueNotNull(outputSchemaValue) {
							if outputSchema, err = jsCapabilitySchemaToGoSchema(rt, outputSchemaValue); err != nil {
								return
							}
						}
						if effectsValue := configObj.Get("effects"); isJsValueNotNull(effectsValue) {
							if effects, err = jsCapabilityEffectsToGoEffects(rt, effectsValue); err != nil {
								return
							}
						}
						if actionEffectsValue := configObj.Get("actionEffects"); isJsValueNotNull(actionEffectsValue) {
							if actionEffects, err = jsCapabilityActionEffectsToGoEffects(rt, actionEffectsValue); err != nil {
								return
							}
						}
					}
				} else {
					err = fmt.Errorf("second argument must be a config object")
					return
				}
				if fn, ok := goja.AssertFunction(call.Argument(2)); ok {
					handler = fn
				} else {
					err = fmt.Errorf("third argument must be a handler function")
					return
				}
				return
			}
		}()

		runErr := p.worker.Run(func(rt *goja.Runtime) (result any, err error) {
			if argErr != nil {
				err = argErr
				return
			}

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Pass a non-null config object with at minimum description and inputSchema fields
  2. If config is built dynamically, add a null check before calling registerCapability

Example fix

// before
await siyuan.agent.registerCapability('myTool', null, handler);

// after
await siyuan.agent.registerCapability('myTool', {
  description: 'My tool',
  inputSchema: { type: 'object', properties: {} }
}, handler);
Defensive patterns

Strategy: validation

Validate before calling

if (config == null || typeof config !== 'object') {
  throw new Error('Config must be a non-null object');
}
await siyuan.agent.registerCapability(name, config, handler);

Type guard

function isNonNullObject(v) {
  return v !== null && v !== undefined && typeof v === 'object';
}

Prevention

When it happens

Trigger: Calling registerCapability('myTool', null, handler), registerCapability('myTool', undefined, handler), or omitting the second argument entirely so goja pads it with undefined.

Common situations: Plugin builds the config object conditionally and it ends up null; the config variable was declared but never assigned; a refactor moved config construction into a function that returns null on some path.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/ee1f5ef2b575cd2a. Report an issue: GitHub.