apache/pulsar · error · IllegalArgumentException
Sink class %s not found
Error message
Sink class %s not found
What it means
Thrown by SinkConfigUtils.validateAndExtractDetails when the sink's class name (sinkClassName) cannot be resolved in the sink package's type pool via ByteBuddy's resolveType. The library validates that the configured sink class exists in the uploaded archive/NAR before creating a sink. It wraps TypePool.Resolution.NoSuchTypeException in an IllegalArgumentException.
Source
Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/SinkConfigUtils.java:478
// thus we should try to find it class name in the NAR service definition
if (sinkClassName == null) {
ConnectorDefinition connectorDefinition = sinkFunction.getFunctionMetaData(ConnectorDefinition.class);
if (connectorDefinition == null) {
throw new IllegalArgumentException(
"Sink package doesn't contain the META-INF/services/pulsar-io.yaml file.");
}
sinkClassName = connectorDefinition.getSinkClass();
if (sinkClassName == null) {
throw new IllegalArgumentException("Failed to extract sink class from archive");
}
}
// check if sink implements the correct interfaces
TypeDefinition sinkClass;
try {
sinkClass = sinkFunction.resolveType(sinkClassName);
} catch (TypePool.Resolution.NoSuchTypeException e) {
throw new IllegalArgumentException(
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) {View on GitHub (pinned to 820761864e)
Solutions
- Verify the className in sinkConfig matches the fully-qualified name of a class implementing org.apache.pulsar.io.core.Sink in the archive
- Run `jar tf <archive>` (or inspect the NAR) to confirm the class file exists at the expected path
- Rebuild/re-upload the connector NAR or function package so it contains the sink class
- Confirm the connector is installed in the functions worker's connectors directory if using a built-in connector
Example fix
// before
sinkConfig.setClassName("org.example.MySinkt");
// after
sinkConfig.setClassName("org.example.MySink"); Defensive patterns
Strategy: validation
Validate before calling
try (Closer c = Closer.create()) {
// verify class exists in the archive before submitting
try (java.util.jar.JarFile jar = new java.util.jar.JarFile(archivePath)) {
String entry = sinkClassName.replace('.', '/') + ".class";
if (jar.getJarEntry(entry) == null) {
throw new IllegalStateException("Sink class " + sinkClassName + " not in archive");
}
}
} Try / catch
try {
admin.sinks().createSink(config, archivePath);
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().contains("not found") && e.getMessage().startsWith("Sink class")) {
log.error("Fix sinkConfig.className; class not present in uploaded archive", e);
} else { throw e; }
} Prevention
- Copy the fully-qualified class name from the connector's docs/source instead of typing it
- Verify with `jar tf archive.jar | grep Sink` before submitting
- After connector upgrades, re-check class names for renames
When it happens
Trigger: Creating/updating a sink whose className does not match any class inside the provided archive or built-in connector NAR; typo in the fully-qualified class name; the class is in the NAR but not visible to the functions worker's classloader.
Common situations: Typos in sinkConfig className; deploying a connector NAR built with a shaded/renamed class; uploading a custom jar missing the sink class; class name changed after a connector upgrade.
Related errors
- Function class %s not found
- Sink class %s does not implement the correct interface
- Transform function class name must be set
- Only one of serdeClassName or schemaType should be set
- When effectively once processing guarantee is specified, ret
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/2f4943866dcdd30b.
Report an issue: GitHub.