apache/pulsar · error · IOException
Class %s does not implement interface %s or %s
Error message
Class %s does not implement interface %s or %s
What it means
getIOSourceClass loads the declared sourceClass from the connector NAR and verifies it implements org.apache.pulsar.functions.api.Source or BatchSource. If the loaded class implements neither, an IOException is thrown because the class cannot be used as a Pulsar IO source.
Source
Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/io/ConnectorUtils.java:79
public static String computeArchiveChecksumHex(Path path) throws IOException {
return HexFormat.of().formatHex(FileUtils.calculateSha256sum(path.toAbsolutePath().normalize().toFile()));
}
/**
* Extract the Pulsar IO Source class from a connector archive.
*/
public static String getIOSourceClass(NarClassLoader narClassLoader) throws IOException {
ConnectorDefinition conf = getConnectorDefinition(narClassLoader);
if (StringUtils.isEmpty(conf.getSourceClass())) {
throw new IOException(
String.format("The '%s' connector does not provide a source implementation", conf.getName()));
}
try {
// Try to load source class and check it implements Source interface
Class<?> sourceClass = narClassLoader.loadClass(conf.getSourceClass());
if (!(Source.class.isAssignableFrom(sourceClass) || BatchSource.class.isAssignableFrom(sourceClass))) {
throw new IOException(String.format("Class %s does not implement interface %s or %s",
conf.getSourceClass(), Source.class.getName(), BatchSource.class.getName()));
}
} catch (Throwable t) {
Exceptions.rethrowIOException(t);
}
return conf.getSourceClass();
}
/**
* Extract the Pulsar IO Sink class from a connector archive.
*/
public static String getIOSinkClass(NarClassLoader narClassLoader) throws IOException {
ConnectorDefinition conf = getConnectorDefinition(narClassLoader);
if (StringUtils.isEmpty(conf.getSinkClass())) {
throw new IOException(
String.format("The '%s' connector does not provide a sink implementation", conf.getName()));
}View on GitHub (pinned to 820761864e)
Solutions
- Set sourceClass in the connector metadata to a class implementing org.apache.pulsar.functions.api.Source (or BatchSource)
- Rebuild the connector NAR after fixing the class
- Check the class implements the interface with the same API version the runtime uses
Example fix
// before
public class MyConnector { /* no interface */ }
// after
public class MyConnector implements Source { public void open(...) {...} public Record<String> read() {...} ... } Defensive patterns
Strategy: validation
Validate before calling
String cls = ConnectorUtils.getConnectorDefinition(loader).getSourceClass();
Class<?> c = Class.forName(cls, false, loader);
if (!Source.class.isAssignableFrom(c) && !BatchSource.class.isAssignableFrom(c)) {
throw new IllegalArgumentException(cls + " is not a Source");
} Type guard
boolean isValidSourceClass(String name, NarClassLoader loader) throws ClassNotFoundException {
Class<?> c = loader.loadClass(name);
return Source.class.isAssignableFrom(c) || BatchSource.class.isAssignableFrom(c);
} Try / catch
try {
String src = ConnectorUtils.getIOSourceClass(loader);
} catch (IOException e) {
if (e.getMessage().contains("does not implement interface")) {
// report bad connector build to connector maintainer
} else { throw e; }
} Prevention
- Always have connector classes implement the api Source/BatchSource interface
- Run a smoke test that loads the NAR via ConnectorUtils in CI
- Pin the pulsar-io-core dependency version to the target runtime
When it happens
Trigger: Calling getIOSourceClass(narClassLoader) where the connector definition names a class that loads successfully but does not implement Source or BatchSource.
Common situations: Connector author pointed sourceClass at a helper/raw class instead of the Source implementation; refactoring renamed or dropped the interface; wrong class name pasted into connector metadata.
Related errors
- Class ${sinkClass} does not implement interface org.apache.p
- Invalid sink type '%s' -- Available sinks are: %s
- Sink package doesn't contain the META-INF/services/pulsar-io
- Failed to extract sink class from archive
- Source class %s does not implement the correct interface
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/3cdb369ab09e82c4.
Report an issue: GitHub.