siyuan-note/siyuan · error
topic required
Error message
topic required
What it means
Beyond the two-argument arity check, the event method validates that the topic (first argument) is a non-empty string, since an empty topic cannot be routed to any subscriber. The promise rejects with 'topic required' when the topic is ''.
Solutions
- Supply a non-empty topic string as the first argument
- Assert/log the topic value before the call to catch empty values
- Skip the publish or fall back to a default topic when the value is empty
- Fix the upstream source (config key, data field) that yields the empty topic
Example fix
// before
await siyuan.event.publish(cfg.channel || '', payload);
// after
if (cfg.channel) { await siyuan.event.publish(cfg.channel, payload); } Defensive patterns
Strategy: validation
Validate before calling
function publishEvent(topic, payload) {
if (typeof topic !== 'string' || topic.length === 0) {
throw new TypeError('event topic must be a non-empty string');
}
return siyuan.event.publish(topic, payload);
} Type guard
function isNonEmptyString(v) {
return typeof v === 'string' && v.length > 0;
} Try / catch
try {
await siyuan.event.publish(topic, payload);
} catch (e) {
if (String(e.message) === 'topic required') {
console.warn('Skipping publish: empty topic', {payload});
return;
}
throw e;
} Prevention
- Validate dynamic topic values before publishing
- Provide fallback/default topics for config-driven channels
- Never construct topics by concatenating possibly-empty segments without a check
When it happens
Trigger: Calling emit('', data) or emit(someVariable, data) where someVariable resolves to an empty string.
Common situations: Topics derived from config or data keys that are missing or empty; template-built topic names where a segment was blank; state not yet initialized when the call fires.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- cannot remove storage root
- Conf.Language(114)
- config.actionEffects contains an empty action
- Field [name] must not be empty
- first argument must be method name string
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/7538f9f961daf412.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/plugin/api_event.go:50
}
}()
event := rt.NewObject()
lo.Must0(event.Set("handler", goja.Null()))
lo.Must0(event.Set("emit", rt.ToValue(func(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
promise, resolve, reject := rt.NewPromise()
var argErr error
var topic string
var eventData any
if len(call.Arguments) < 2 {
argErr = fmt.Errorf("topic and event required")
} else {
topic = call.Argument(0).String()
if topic == "" {
argErr = fmt.Errorf("topic required")
} else {
eventData = call.Argument(1).Export()
}
}
runErr := p.worker.Run(func(rt *goja.Runtime) (result any, err error) {
if argErr != nil {
err = argErr
return
}
p.bus.Publish(topic, eventData)
return
}, func(rt *goja.Runtime, result any, err error) {
if lo.IsNil(err) {
if resolveErr := resolve(result); resolveErr != nil {
logging.LogErrorf("[plugin:%s] siyuan.event.emit resolve: %v", p.Name, resolveErr)
}
} else {View on GitHub (pinned to 9f775e8a12)