karatelabs/karate · error · RuntimeException
ka:dispatch trigger must be non-empty after `@`; got
Error message
ka:dispatch trigger must be non-empty after `@`; got `${attributeValue}` What it means
After splitting ka:dispatch's 'event @ trigger' value on '@', doProcess validates that the trigger substring after the '@' is non-empty and throws a RuntimeException otherwise. An empty trigger gives an unactionable dispatch binding, so the library fails fast with the offending attribute value in the message.
Solutions
- Provide a non-empty trigger name after the '@', e.g. ka:dispatch="save @ form-submit"
- If a dynamic trigger, ensure the interpolated value is populated at render time
- If no trigger is needed, remove the '@' and write just the event name
Example fix
<!-- before --> <button ka:dispatch="save @"></button> <!-- after --> <button ka:dispatch="save @ form-submit"></button>
Defensive patterns
Strategy: validation
Validate before calling
String[] parts = attrValue.split("@", -1); if (parts.length == 2 && parts[1].trim().isEmpty()) throw new IllegalArgumentException("empty ka:dispatch trigger: " + attrValue); Try / catch
try { render(template, model); } catch (RuntimeException e) { if (e.getMessage() != null && e.getMessage().contains("trigger must be non-empty")) { log.error("bad ka:dispatch: {}", e.getMessage()); } throw e; } Prevention
- Always provide a trigger name after '@' in ka:dispatch
- Check interpolated attribute values are non-empty at render time
- Remove the '@' entirely when no trigger is intended
When it happens
Trigger: Writing ka:dispatch="eventName @" or "eventName @ " (only whitespace after '@'), often from an incomplete edit or a templated value that rendered empty.
Common situations: Deleting the trigger name while refactoring; interpolating a variable into the attribute that resolved to empty string; copy-paste truncation.
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
- ka:dispatch supports a single `event @ trigger` delimiter…
- ka:data requires format 'varName:expression', got
- karate-markup does not support param lists in th:fragment…
- ka:dispatch requires an event name; got
- th:each requires `name : expression` form
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/0529321158165d60.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/markup/KaDispatchProcessor.java:97
// Split `<dispatched-event> @ <trigger-event>`. The `@`
// delimiter is optional; without it the dispatch fires on click
// (default, no htmx dependency). With it, the LHS is the CustomEvent
// name and the RHS is the DOM/htmx trigger emitted via
// `hx-on:<trigger>` (htmx must be loaded on the page).
String av = attributeValue.trim();
String eventName = av;
String triggerOn = null;
int at = av.indexOf('@');
if (at >= 0) {
if (av.lastIndexOf('@') != at) {
throw new RuntimeException(
"ka:dispatch supports a single `event @ trigger` delimiter; got `"
+ attributeValue + "`");
}
eventName = av.substring(0, at).trim();
triggerOn = av.substring(at + 1).trim();
if (triggerOn.isEmpty()) {
throw new RuntimeException(
"ka:dispatch trigger must be non-empty after `@`; got `"
+ attributeValue + "`");
}
}
if (eventName.isEmpty()) {
throw new RuntimeException(
"ka:dispatch requires an event name; got `"
+ attributeValue + "`");
}
MarkupTemplateContext kec = (MarkupTemplateContext) ctx;
String detailJson = "{}";
String vals = tag.getAttributeValue(getDialectPrefix(), VALS);
if (vals != null && !vals.isEmpty()) {
Object result = kec.evalLocalAsObject(vals);
if (result instanceof Map) {
detailJson = Json.of(result).toString();
} else if (result != null) {
logger.warn("ka:dispatch ignored ka:vals — did not evaluate to an object: {}", vals);View on GitHub (pinned to a22eb90246)