karatelabs/karate · error · RuntimeException
boot.ext(' '): does not implement io.karatelabs.core.Ext
Error message
boot.ext('${name}'): ${className} does not implement io.karatelabs.core.Ext What it means
boot.ext(name) resolves the name to a class via the naming convention, instantiates it, and verifies the instance implements io.karatelabs.core.Ext. If the class loads but does not implement Ext, a RuntimeException is thrown naming both the requested extension and the offending class.
Solutions
- Make the resolved class implement io.karatelabs.core.Ext (implement its methods).
- Rebuild the extension against the karate version in use so it implements the current Ext interface/package.
- Remove or rename the unrelated class occupying the name-convention FQCN.
- Use a different extension name whose conventional class is free.
Example fix
// before
public class MyExt { } // wrong package, no Ext interface
// after
import io.karatelabs.core.Ext;
public class MyExt implements Ext {
public void onBoot(Suite suite) { }
} Defensive patterns
Strategy: validation
Validate before calling
// before boot.ext(name), verify the class implements Ext
Class<?> c = Class.forName(resolvedFqcn);
if (!io.karatelabs.core.Ext.class.isAssignableFrom(c)) {
throw new IllegalStateException(resolvedFqcn + " must implement io.karatelabs.core.Ext");
} Try / catch
try {
boot.ext(name);
} catch (RuntimeException e) {
// message names the offending class — fix its implements clause or rebuild against current karate
} Prevention
- Always implement io.karatelabs.core.Ext from the same karate version you run against.
- Rebuild extensions when upgrading karate.
- Don't place unrelated classes at the extension naming-convention FQCN.
When it happens
Trigger: A class exists at the name-convention location (so ClassNotFoundException does not fire) but it does not implement io.karatelabs.core.Ext — e.g. an unrelated class occupying the expected FQCN, or an Ext implementation compiled against a different package/version of the interface.
Common situations: Upgrading karate where the Ext interface package changed (e.g. io.karatelabs vs older package) leaving an old implementation in place; accidentally placing a helper class at the conventional extension FQCN; two extensions colliding on the same class name.
Related errors
- boot.ext(' '): not on classpath. Expected (name-convention…
- boot.read: file not found
- boot.ext: name is null or empty
- boot.ext(' '): failed to construct
- boot.classpath: dir is null — pass a project-relative…
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/1b83757c9c301c7c.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/core/BootBinding.java:227
* <p>Same name twice returns the same singleton instance.</p>
*/
public Ext ext(String name) {
if (name == null || name.isBlank()) {
throw new IllegalArgumentException("boot.ext: name is null or empty");
}
// Singleton-per-name within this BootBinding (which is itself per-Suite).
for (Ext existing : exts) {
if (name.equals(extShortName(existing))) {
return existing;
}
}
String className = extClassName(name);
Ext ext;
try {
Class<?> cls = Class.forName(className);
Object instance = cls.getDeclaredConstructor().newInstance();
if (!(instance instanceof Ext)) {
throw new RuntimeException(
"boot.ext('" + name + "'): " + className
+ " does not implement io.karatelabs.core.Ext");
}
ext = (Ext) instance;
} catch (ClassNotFoundException e) {
throw new RuntimeException(
"boot.ext('" + name + "'): not on classpath. Expected "
+ className + " (name-convention resolution).", e);
} catch (Exception e) {
throw new RuntimeException(
"boot.ext('" + name + "'): failed to construct " + className
+ " — " + e.getMessage(), e);
}
// Fire onBoot eagerly per K43. Throws here fail the Suite.
ext.onBoot(suite);
exts.add(ext);
registrar.accept(ext);
logger.info("ext booted: {} ({})", name, ext.getClass().getName());View on GitHub (pinned to a22eb90246)