apache/pulsar · error · IllegalArgumentException

Transform function class name must be set

Error message

Transform function class name must be set

What it means

After reading the FunctionDefinition from META-INF/services/pulsar-io.yaml, the library expects getFunctionClass() to name the transform function class. Thrown when the service descriptor exists but its functionClass field is null/empty.

Source

Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/SinkConfigUtils.java:497

                    String.format("Sink class %s not found", sinkClassName), e);
        }

        String functionClassName = sinkConfig.getTransformFunctionClassName();
        TypeDefinition typeArg;
        ValidatableFunctionPackage inputFunction;
        if (transformFunction != null) {
            // if function class name in sink config is not set, this should be a built-in function
            // thus we should try to find it class name in the NAR service definition
            if (functionClassName == null) {
                FunctionDefinition functionDefinition =
                        transformFunction.getFunctionMetaData(FunctionDefinition.class);
                if (functionDefinition == null) {
                    throw new IllegalArgumentException(
                            "Function package doesn't contain the META-INF/services/pulsar-io.yaml file.");
                }
                functionClassName = functionDefinition.getFunctionClass();
                if (functionClassName == null) {
                    throw new IllegalArgumentException("Transform function class name must be set");
                }
            }
            TypeDefinition functionClass;
            try {
                functionClass = transformFunction.resolveType(functionClassName);
            } catch (TypePool.Resolution.NoSuchTypeException e) {
                throw new IllegalArgumentException(
                        String.format("Function class %s not found", functionClassName), e);
            }
            // extract type from transform function class
            if (!getRawFunctionTypes(functionClass, false)[1].asErasure().isAssignableTo(Record.class)) {
                throw new IllegalArgumentException("Sink transform function output must be of type Record");
            }
            typeArg = getFunctionTypes(functionClass, false)[0];
            inputFunction = transformFunction;
        } else {
            // extract type from sink class
            typeArg = getSinkType(sinkClass);

View on GitHub (pinned to 820761864e)

Solutions

  1. Add/repair the functionClass entry in META-INF/services/pulsar-io.yaml of the transform function package
  2. Or set sinkConfig.setTransformFunctionClassName(...) explicitly to bypass reading it from the descriptor

Example fix

# before
name: my-transform
# after
name: my-transform
functionClass: org.example.MyTransformFunction
Defensive patterns

Strategy: validation

Validate before calling

// verify descriptor declares functionClass
java.util.Properties p = new java.util.Properties();
// read META-INF/services/pulsar-io.yaml as text and assert 'functionClass:' key present
String yaml = new String(java.util.zip.GZIPInputStream.class.getResourceAsStream(
    "/META-INF/services/pulsar-io.yaml").readAllBytes());
if (!yaml.contains("functionClass:")) throw new IllegalStateException("pulsar-io.yaml missing functionClass");

Try / catch

try {
  admin.sinks().createSink(config, pkgPath);
} catch (IllegalArgumentException e) {
  if (e.getMessage() != null && e.getMessage().contains("Transform function class name must be set")) {
    config.setTransformFunctionClassName("org.example.MyTransform");
  } else { throw e; }
}

Prevention

When it happens

Trigger: The pulsar-io.yaml in the transform function package exists but omits the functionClass property, and sinkConfig.transformFunctionClassName is null.

Common situations: Hand-written or templated pulsar-io.yaml missing the functionClass key; a build step that filtered the yaml resource out partially.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/d0b5fe9ba4e40d67. Report an issue: GitHub.