apache/beam · error · UnsupportedOperationException

${config}

Error message

${config}

What it means

JavaRowUdf selects how to build the UDF function: from an inline expression, a callable class, or a named function on a path. If none of expression, callable, or name is set in the config, createFunction has no creation strategy and throws UnsupportedOperationException with the config's toString as the message.

Source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/schemas/transforms/providers/JavaRowUdf.java:193

          Function.class,
          new TypeDescriptors.TypeVariableExtractor<Function<InputT, OutputT>, OutputT>() {});
    }
  }

  @SuppressWarnings({
    "nullness" // TODO(https://github.com/apache/beam/issues/20497)
  })
  private static FunctionAndType createFunction(Configuration config, Schema inputSchema)
      throws ReflectiveOperationException, StringCompiler.CompileException, MalformedURLException {
    config.validate();
    if (!Strings.isNullOrEmpty(config.getExpression())) {
      return createFunctionFromExpression(config.getExpression(), inputSchema);
    } else if (!Strings.isNullOrEmpty(config.getCallable())) {
      return createFuctionFromCallable(config.getCallable());
    } else if (!Strings.isNullOrEmpty(config.getName())) {
      return createFunctionFromName(config.getName(), config.getPath());
    } else {
      throw new UnsupportedOperationException(config.toString());
    }
  }

  private static FunctionAndType createFunctionFromExpression(String expression, Schema inputSchema)
      throws StringCompiler.CompileException, ReflectiveOperationException {
    if (inputSchema.hasField(expression)) {
      final int ix = inputSchema.indexOf(expression);
      return new FunctionAndType(
          inputSchema.getField(expression).getType(), (Row row) -> row.getValue(ix));
    } else {
      Map<String, Type> fieldTypes = new HashMap<>();
      for (Schema.Field field : inputSchema.getFields()) {
        if (expression.indexOf(field.getName()) != -1) {
          fieldTypes.put(field.getName(), typeFromFieldType(field.getType()));
        }
      }
      Type type = StringCompiler.guessExpressionType(expression, fieldTypes);
      StringBuilder source = new StringBuilder();

View on GitHub (pinned to 12126d8942)

Solutions

  1. Set one of 'expression', 'callable', or 'name' in the UDF configuration
  2. Fix typos in config keys so the intended option is populated
  3. Validate the config object before passing it to the transform

Example fix

// before
udf:
  language: sql
# after
udf:
  language: sql
  expression: "count * 2"
Defensive patterns

Strategy: validation

Validate before calling

if (Strings.isNullOrEmpty(config.getExpression())
    && Strings.isNullOrEmpty(config.getCallable())
    && Strings.isNullOrEmpty(config.getName()))
  throw new IllegalArgumentException("UDF config requires expression, callable, or name");

Prevention

When it happens

Trigger: createFunction called (via functionAndType) with a JavaRowUdf config where getExpression(), getCallable(), and getName() are all null or empty strings.

Common situations: Incomplete YAML/JSON config for the UDF transform; typo'd config keys so values land in the wrong fields; config built programmatically without setting any of the three options.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/bddc0c45c8e74509. Report an issue: GitHub.