{"record":{"id":"896ebbc5c116ffeb","repo":"apache/beam","slug":"must-not-throw-checked-exception","errorCode":null,"errorMessage":" must not throw checked exception","messagePattern":" must not throw checked exception","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/ScalarFunctionImpl.java","lineNumber":135,"sourceCode":"   * @param method method that is used to implement the function\n   * @param jarPath Path to jar that contains the method.\n   * @return created {@link Function}\n   */\n  public static Function create(Method method, String jarPath) {\n    validateMethod(method);\n    CallImplementor implementor = createImplementor(method);\n    return new ScalarFunctionImpl(method, implementor, jarPath);\n  }\n\n  protected static void validateMethod(Method method) {\n    if (!Modifier.isStatic(method.getModifiers())) {\n      Class clazz = method.getDeclaringClass();\n      if (!classHasPublicZeroArgsConstructor(clazz)) {\n        throw RESOURCE.requireDefaultConstructor(clazz.getName()).ex();\n      }\n    }\n    if (method.getExceptionTypes().length != 0) {\n      throw new RuntimeException(method.getName() + \" must not throw checked exception\");\n    }\n  }\n\n  @Override\n  public RelDataType getReturnType(RelDataTypeFactory typeFactory) {\n    return CalciteUtils.sqlTypeWithAutoCast(typeFactory, method.getGenericReturnType());\n  }\n\n  @Override\n  public CallImplementor getImplementor() {\n    return implementor;\n  }\n\n  /**\n   * Version of {@link ReflectiveCallNotNullImplementor} that does parameter conversion for Beam\n   * UDFs.\n   */\n  private static class ScalarReflectiveCallNotNullImplementor","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/ScalarFunctionImpl.java#L117-L153","documentation":"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.","triggerScenarios":"Registering a scalar function via ScalarFunctionImpl.create whose method signature ends in 'throws SomeException' — the exception types array is non-empty at validateMethod.","commonSituations":"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.","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)."],"exampleFix":"// before\npublic LocalDate parse(String s) throws ParseException {\n  return new SimpleDateFormat(\"yyyy-MM-dd\").parse(s).toInstant()...;\n}\n// after\npublic LocalDate parse(String s) {\n  try {\n    return LocalDate.parse(s);\n  } catch (DateTimeParseException e) {\n    throw new IllegalArgumentException(\"bad date: \" + s, e);\n  }\n}","handlingStrategy":"validation","validationCode":"static void checkNoCheckedExceptions(java.lang.reflect.Method m) {\n  if (m.getExceptionTypes().length > 0)\n    throw new IllegalStateException(m.getName() + \" must not declare exceptions\");\n  if (!java.lang.reflect.Modifier.isPublic(m.getDeclaringClass().getModifiers())\n      || java.util.Arrays.stream(m.getDeclaringClass().getConstructors())\n          .noneMatch(c -> c.getParameterCount() == 0))\n    throw new IllegalStateException(m.getDeclaringClass() + \" needs a public zero-arg constructor\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  ScalarFunctionImpl.create(method);\n} catch (RuntimeException e) {\n  if (e.getMessage().contains(\"must not throw checked exception\")) {\n    throw new IllegalStateException(\"Remove throws clause / catch inside the UDF method\", e);\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["java","udf","checked-exception","calcite","beam-sql"],"backgroundTag":"invalid-argument-value","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}