apache/beam · error · RuntimeException
must not throw checked exception
Error message
must not throw checked exception
What it means
ScalarFunctionImpl.validateMethod checks a candidate UDF method before wrapping it in a Calcite function: its declaring class must have a public zero-arg constructor and the method must declare no exceptions. A method that declares checked (or any) exception types would leak exceptions through Calcite's invoke path, so create() fails with a RuntimeException naming the method.
Source
Thrown at sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/ScalarFunctionImpl.java:135
* @param method method that is used to implement the function
* @param jarPath Path to jar that contains the method.
* @return created {@link Function}
*/
public static Function create(Method method, String jarPath) {
validateMethod(method);
CallImplementor implementor = createImplementor(method);
return new ScalarFunctionImpl(method, implementor, jarPath);
}
protected static void validateMethod(Method method) {
if (!Modifier.isStatic(method.getModifiers())) {
Class clazz = method.getDeclaringClass();
if (!classHasPublicZeroArgsConstructor(clazz)) {
throw RESOURCE.requireDefaultConstructor(clazz.getName()).ex();
}
}
if (method.getExceptionTypes().length != 0) {
throw new RuntimeException(method.getName() + " must not throw checked exception");
}
}
@Override
public RelDataType getReturnType(RelDataTypeFactory typeFactory) {
return CalciteUtils.sqlTypeWithAutoCast(typeFactory, method.getGenericReturnType());
}
@Override
public CallImplementor getImplementor() {
return implementor;
}
/**
* Version of {@link ReflectiveCallNotNullImplementor} that does parameter conversion for Beam
* UDFs.
*/
private static class ScalarReflectiveCallNotNullImplementorView on GitHub (pinned to 12126d8942)
Solutions
- Remove the throws clause and catch the checked exception inside the method, rethrowing as an unchecked exception.
- Handle the failure in-band, e.g. return null for unparseable input instead of throwing.
- Wrap the library call in try/catch and convert to RuntimeException with context if the UDF should fail the query.
- Ensure the declaring class also has a public no-arg constructor (the other requirement of validateMethod).
Example fix
// before
public LocalDate parse(String s) throws ParseException {
return new SimpleDateFormat("yyyy-MM-dd").parse(s).toInstant()...;
}
// after
public LocalDate parse(String s) {
try {
return LocalDate.parse(s);
} catch (DateTimeParseException e) {
throw new IllegalArgumentException("bad date: " + s, e);
}
} Defensive patterns
Strategy: validation
Validate before calling
static void checkNoCheckedExceptions(java.lang.reflect.Method m) {
if (m.getExceptionTypes().length > 0)
throw new IllegalStateException(m.getName() + " must not declare exceptions");
if (!java.lang.reflect.Modifier.isPublic(m.getDeclaringClass().getModifiers())
|| java.util.Arrays.stream(m.getDeclaringClass().getConstructors())
.noneMatch(c -> c.getParameterCount() == 0))
throw new IllegalStateException(m.getDeclaringClass() + " needs a public zero-arg constructor");
} Try / catch
try {
ScalarFunctionImpl.create(method);
} catch (RuntimeException e) {
if (e.getMessage().contains("must not throw checked exception")) {
throw new IllegalStateException("Remove throws clause / catch inside the UDF method", e);
}
throw e;
} Prevention
- Catch checked exceptions inside UDF methods and convert to unchecked or null returns.
- Never copy throws clauses from library interfaces into UDF signatures.
- Ensure declaring classes expose a public no-arg constructor.
When it happens
Trigger: Registering a scalar function via ScalarFunctionImpl.create whose method signature ends in 'throws SomeException' — the exception types array is non-empty at validateMethod.
Common situations: Wrapping an existing library call that throws checked exceptions (IOException, ParseException, SQLException) directly as a UDF; inheriting a method signature with throws clauses; auto-generating UDF stubs from interfaces with throws clauses.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- No UdfProvider implementation found in ${jarPath}. Create a
- Unexpected null when creating synthetic Beam JdbcDriver
- No method annotated with @%s found in class %s.
- Method %s is not public.
- Unable to get current schema name from JdbcConnection. Assum
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/896ebbc5c116ffeb.
Report an issue: GitHub.