siyuan-note/siyuan · error
failed to serialize config.
Error message
failed to serialize config.%s: %v
What it means
unmarshalCapabilityJSON serializes a JS capability config field (identified by name, e.g. config.effects or config.actionEffects) to JSON before decoding it into a Go struct. When goja's MarshalJSON fails, the error names the field. This means the JS value for that config field cannot be represented as JSON at all.
Solutions
- Ensure the named config field is a plain JSON object (string keys, serializable values)
- Remove functions, Symbols, and circular references from the object
- Sanitize in JS: JSON.parse(JSON.stringify(value)) before passing it
- Read the wrapped error to locate the offending value
Example fix
// before
config.actionEffects = { run: { handler: (args) => doSomething() } } // function not serializable
// after
config.actionEffects = { run: { readOnlyHint: false, destructiveHint: true } }; Defensive patterns
Strategy: validation
Validate before calling
function isJsonSerializable(v) {
try { JSON.stringify(v); return true; } catch { return false; }
}
if (!isJsonSerializable(config.effects)) throw new Error("config.effects must be JSON-serializable"); Try / catch
try {
registerCapability(config);
} catch (e) {
if (String(e).includes("failed to serialize config.")) {
console.error("Capability config contains non-serializable values", e);
}
} Prevention
- Keep capability config free of functions and circular references
- Sanitize with JSON.parse(JSON.stringify(...)) before registering
- Keep config builders pure — no getters with side effects
When it happens
Trigger: Passing a non-serializable value as config.effects or config.actionEffects: circular references, functions as values, Symbol keys, or a throwing getter somewhere in the object graph.
Common situations: Plugin authors embed callback functions inside the effects object expecting them to be invoked, or accidentally share a circular config object between plugins; goja marshalling chokes on it.
Understand the failure class
Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.
Related errors
- failed to serialize inputSchema
- invalid config.
- invalid json schema
- builtin color must not be null
- builtin style must not be null
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/7b98a7670c0e5d6b.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/plugin/api_agent.go:302
}
func jsCapabilityActionEffectsToGoEffects(rt *goja.Runtime, value goja.Value) (map[string]tools.ToolEffects, error) {
actionEffects := map[string]tools.ToolEffects{}
if err := unmarshalCapabilityJSON(rt, value, &actionEffects, "actionEffects"); err != nil {
return nil, err
}
for action := range actionEffects {
if strings.TrimSpace(action) == "" {
return nil, fmt.Errorf("config.actionEffects contains an empty action")
}
}
return actionEffects, nil
}
func unmarshalCapabilityJSON(rt *goja.Runtime, value goja.Value, target any, field string) error {
jsonValue, err := value.ToObject(rt).MarshalJSON()
if err != nil {
return fmt.Errorf("failed to serialize config.%s: %v", field, err)
}
if err = json.Unmarshal(jsonValue, target); err != nil {
return fmt.Errorf("invalid config.%s: %v", field, err)
}
return nil
}
View on GitHub (pinned to 9f775e8a12)