karatelabs/karate · error · java.lang.RuntimeException

<cause message>

Error message

<cause message>

What it means

JavaType resolves a Java class by name; when Class.forName fails it throws a RuntimeException whose message/cause is the last ClassNotFoundException (or a previously captured resolution failure). It means the requested Java class is not on the classpath.

Solutions

  1. Verify the fully-qualified class name for typos and correct package
  2. Add the artifact containing the class to the test classpath (pom.xml/gradle dependency)
  3. Check the cause chain — `last` may point to an earlier, more specific resolution failure
  4. Use an import alias (karate.configure / Java import binding) if the class is available under another name

Example fix

// before
var Tcp = Java.type('com.example.tcp.Client'); // ClassNotFoundException
// after
// add the dependency, then:
var Tcp = Java.type('com.example.tcp.Client'); // resolves
Defensive patterns

Strategy: try-catch

Validate before calling

try { Class.forName(className); } catch (ClassNotFoundException e) { /* fail fast with clear message */ }

Try / catch

try {
  var T = Java.type('com.example.Client');
} catch (e) {
  karate.log('class not on classpath:', 'com.example.Client');
}

Prevention

When it happens

Trigger: `Java.type('some.Class')` (or JavaType construction) with a class name that has no import alias match and cannot be loaded by Class.forName.

Common situations: Typo in fully-qualified class name; dependency jar missing from the test classpath; class present only in a different Maven module/profile; package renames across library versions.

Related errors


AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/6c4eec724c8434c3. Report an issue: GitHub.

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/js/JavaType.java:59

        // child loader (e.g. JUnit Platform Console Launcher's --cp loader)
        // are visible. Class.forName(name) uses the caller's defining loader
        // (this bundle's), which can't see those classes. Fall back to that
        // loader if the TCCL isn't set or doesn't have the class.
        Class<?> resolved = null;
        ClassNotFoundException last = null;
        ClassLoader tccl = Thread.currentThread().getContextClassLoader();
        if (tccl != null) {
            try {
                resolved = Class.forName(className, true, tccl);
            } catch (ClassNotFoundException e) {
                last = e;
            }
        }
        if (resolved == null) {
            try {
                resolved = Class.forName(className);
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(last != null ? last : e);
            }
        }
        this.clazz = resolved;
    }

    @Override
    public Object construct(Object[] args) {
        return JavaUtils.construct(clazz, args);
    }

    @Override
    public Object invokeMethod(String name, Object[] args) {
        return JavaUtils.convertIfArray(JavaUtils.invokeStatic(clazz, name, args));
    }

    @Override
    public Object getProperty(String name) {
        return JavaUtils.convertIfArray(JavaUtils.getStatic(clazz, name));

View on GitHub (pinned to a22eb90246)