apache/beam · error · RuntimeException
KeepFn %s must return a boolean, but returns %s instead.
Error message
KeepFn %s must return a boolean, but returns %s instead.
What it means
JavaFilterTransformProvider compiles the user-supplied KeepFn predicate via StringCompiler and validates its output type. It throws this RuntimeException when the compiled keep function's return type (ignoring nullability) is not Schema.FieldType.BOOLEAN, since a filter predicate must produce a boolean.
Source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/schemas/transforms/providers/JavaFilterTransformProvider.java:130
private final Configuration configuration;
JavaFilterTransform(Configuration configuration) {
this.configuration = configuration;
}
@Override
public PCollectionRowTuple expand(PCollectionRowTuple input) {
Schema inputSchema = input.get(INPUT_ROWS_TAG).getSchema();
JavaRowUdf keepFn;
try {
keepFn = new JavaRowUdf(this.configuration.getKeep(), inputSchema);
} catch (MalformedURLException
| ReflectiveOperationException
| StringCompiler.CompileException exn) {
throw new RuntimeException(exn);
}
if (!keepFn.getOutputType().withNullable(false).equals(Schema.FieldType.BOOLEAN)) {
throw new RuntimeException(
String.format(
"KeepFn %s must return a boolean, but returns %s instead.",
this.configuration.getKeep(), keepFn.getOutputType()));
}
boolean handleErrors = ErrorHandling.hasOutput(configuration.getErrorHandling());
Schema errorSchema = ErrorHandling.errorSchema(inputSchema);
PCollectionTuple pcolls =
input
.get(INPUT_ROWS_TAG)
.apply(
"Filter",
ParDo.of(createDoFn(keepFn, errorSchema, handleErrors))
.withOutputTags(filteredValues, TupleTagList.of(errorValues)));
pcolls.get(filteredValues).setRowSchema(inputSchema);
pcolls.get(errorValues).setRowSchema(errorSchema);
PCollectionRowTuple result =View on GitHub (pinned to 12126d8942)
Solutions
- Change the KeepFn/expression so its return type is boolean
- Wrap the expression in a comparison producing a boolean (e.g. 'field != null && field > 0')
- Inspect keepFn.getOutputType() before expanding to catch the mismatch early
Example fix
// before StringCompiler expression: "input.getCount()" // returns long // after "input.getCount() > 0" // returns boolean
Defensive patterns
Strategy: validation
Validate before calling
if (!keepFn.getOutputType().withNullable(false).equals(Schema.FieldType.BOOLEAN))
throw new IllegalArgumentException("KeepFn must return boolean"); Type guard
boolean returnsBoolean(TypeDescriptor<?> t) { return Schema.FieldType.of(t).withNullable(false).equals(Schema.FieldType.BOOLEAN); } Try / catch
try { expand(input); } catch (RuntimeException e) { if (e.getMessage().contains("must return a boolean")) { /* fix expression */ } else throw e; } Prevention
- Write filter expressions that end in a boolean comparison
- Type-check keepFn output before running the pipeline
When it happens
Trigger: expand() calls the compiled keepFn and checks getOutputType(); if the user-provided expression/callable returns e.g. String, Long, or Void, the check fails and the RuntimeException is thrown.
Common situations: Writing a filter expression that returns a non-boolean value (e.g. a string comparison result, a numeric value); supplying a callable whose return type is Object or wrapped.
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
- Provided coders for type arguments of %s contain incompatibi
- Can't cast non-numeric types: +input
- Can't cast numbers to non-numeric type: +output
- GroupByKey requires its input to use KvCoder
- %s is not compatible with %s
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/2cf0b2db8e9b0532.
Report an issue: GitHub.