apache/pulsar · error · IllegalArgumentException

Function class %s not found

Error message

Function class %s not found

What it means

Thrown when the transform function class name resolved from config/service descriptor cannot be found in the transform function package's type pool. Mirrors error 1470 but for the transform function class of a sink with a transform stage.

Source

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

            // 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);
            inputFunction = sinkFunction;
        }

        if (sinkConfig.getTopicToSerdeClassName() != null) {
            for (String serdeClassName : sinkConfig.getTopicToSerdeClassName().values()) {
                ValidatorUtils.validateSerde(serdeClassName, typeArg, inputFunction.getTypePool(), true);
            }

View on GitHub (pinned to 820761864e)

Solutions

  1. Check that transformFunctionClassName matches a class in the uploaded archive (`jar tf`)
  2. Re-upload a package containing the transform function class
  3. Fix the functionClass entry in META-INF/services/pulsar-io.yaml if that is the source of the name

Example fix

// before
sinkConfig.setTransformFunctionClassName("org.example.OldTransform");
// after
sinkConfig.setTransformFunctionClassName("org.example.NewTransform");
Defensive patterns

Strategy: validation

Validate before calling

try (java.util.jar.JarFile jar = new java.util.jar.JarFile(pkgPath)) {
  String entry = transformClassName.replace('.', '/') + ".class";
  if (jar.getJarEntry(entry) == null) {
    throw new IllegalStateException("Transform class " + transformClassName + " not in package");
  }
}

Try / catch

try {
  admin.sinks().createSink(config, pkgPath);
} catch (IllegalArgumentException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("Function class")) {
    log.error("transformFunctionClassName not found in package; align config with artifact", e);
  } else { throw e; }
}

Prevention

When it happens

Trigger: sinkConfig.transformFunctionClassName (or the value from pulsar-io.yaml) names a class absent from the uploaded transform function archive.

Common situations: Typos in the function class name; class renamed/refactored between versions; package uploaded is stale relative to the config.

Related errors


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