provectus/kafka-ui · error · ValidationException
Unexpected script result
Error message
Unexpected script result: %s, Boolean should be returned instead
What it means
MessageFilters.test evaluates a user-supplied Groovy filter script per message and requires the script to return a Boolean. If the compiled script evaluates to anything else (String, Map, null, Integer), a ValidationException is thrown telling the user to return a Boolean.
Solutions
- Make the script's last evaluated expression a boolean, e.g. `return value != null`
- Wrap non-boolean logic in a comparison: `record.key == 'x'` instead of `record.key`
- Test the script on a single message first; remember null results also fail
Example fix
// before (script) value?.name // after (script) value?.name == 'my-event'
Defensive patterns
Strategy: validation
Validate before calling
function validateFilterScript(src) {
const result = evalCompiledPreview(src); // run against a sample message in a sandbox
if (typeof result !== 'boolean') {
throw new Error('Filter must evaluate to a boolean, got: ' + typeof result);
}
} Type guard
const isBooleanResult = (r) => typeof r === 'boolean';
Try / catch
try {
const filter = MessageFilters.compile(script);
} catch (ValidationException e) {
if (e.getMessage().contains('Boolean should be returned')) {
showHint('End your script with a boolean expression, e.g. value != null');
}
} Prevention
- End every Groovy filter with an explicit comparison or `return true/false`
- Never rely on truthy coercion — Groovy results are checked with instanceof Boolean
- Test scripts against a real message before saving the filter
When it happens
Trigger: Entering a filter in the UI 'Filter messages' dialog whose last expression doesn't evaluate to true/false, e.g. `value != null` returning a String, or a script ending with a statement that returns null.
Common situations: Scripts copied from examples that print or return objects; forgetting `return true/false` or a final boolean expression; using `record.value == null` styles that yield null in edge cases; treating it like a predicate language where truthiness coercion happens (Groovy is not used that way here).
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Script syntax error
- Invalid format for webclient.maxInMemoryBufferSize
- seekTo should be set if seekType is
- Wrong seekTo argument format. See API docs for details
- 'name' property not set for serde
AI-assisted analysis of provectus/kafka-ui@83b5a60cc0 (2026-09-08).
Data as JSON: /api/errors/9f5a9e9716384892.
Report an issue: GitHub.
Appendix: source
Thrown at kafka-ui-api/src/main/java/com/provectus/kafka/ui/emitter/MessageFilters.java:62
var jsonSlurper = new JsonSlurper();
return new Predicate<TopicMessageDTO>() {
@SneakyThrows
@Override
public boolean test(TopicMessageDTO msg) {
var bindings = engine.createBindings();
bindings.put("partition", msg.getPartition());
bindings.put("offset", msg.getOffset());
bindings.put("timestampMs", msg.getTimestamp().toInstant().toEpochMilli());
bindings.put("keyAsText", msg.getKey());
bindings.put("valueAsText", msg.getContent());
bindings.put("headers", msg.getHeaders());
bindings.put("key", parseToJsonOrReturnAsIs(jsonSlurper, msg.getKey()));
bindings.put("value", parseToJsonOrReturnAsIs(jsonSlurper, msg.getContent()));
var result = compiledScript.eval(bindings);
if (result instanceof Boolean) {
return (Boolean) result;
} else {
throw new ValidationException(
"Unexpected script result: %s, Boolean should be returned instead".formatted(result));
}
}
};
}
@Nullable
private static Object parseToJsonOrReturnAsIs(JsonSlurper parser, @Nullable String str) {
if (str == null) {
return null;
}
try {
return parser.parseText(str);
} catch (Exception e) {
return str;
}
}
View on GitHub (pinned to 83b5a60cc0)