karatelabs/karate · error · java.lang.RuntimeException

<cause message>

Error message

<cause message>

What it means

JavaUtils.invokeStatic reflects a static method call; any InvocationTargetException is unwrapped: RuntimeExceptions and Errors are rethrown as-is, and anything else becomes a RuntimeException carrying the cause's message (cause == null falls back to e.getMessage()). So this error surfaces the target method's own failure.

Solutions

  1. Read the cause message — the root failure is inside the invoked Java method, not the bridge
  2. Fix the inputs or state that make the Java method throw
  3. Wrap the Java method so it converts checked exceptions to meaningful RuntimeExceptions
  4. Catch the exception in JS with a JS try/catch if the failure is an expected business condition

Example fix

// before
public static Config load(String path) throws IOException {
  return read(path); // surfaces as RuntimeException: <cause message>
}
// after
public static Config load(String path) {
  try {
    return read(path);
  } catch (IOException e) {
    throw new RuntimeException("config load failed: " + path, e);
  }
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  Java.type('Utils').staticMethod(arg);
} catch (e) {
  // e carries the Java method's own failure; inspect and decide
  karate.log('java static call failed:', e.message);
}

Prevention

When it happens

Trigger: A static Java method invoked from JS (e.g. Java.type('X').staticMethod(...)) throws a checked exception; JavaUtils unwraps the InvocationTargetException and rethrows it as RuntimeException with the cause message.

Common situations: Java utility methods throwing checked exceptions (IOException etc.) when called from a Karate feature; user-written Java helpers failing on bad input; IllegalAccessException variants are handled separately as typeError, so this specifically means the method itself threw.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/js/JavaUtils.java:71

        }
    }

    static Object invokeStatic(Class<?> clazz, String name, Object[] args) {
        Method method = findMethod(clazz, name, args);
        if (method == null) {
            throw JsErrorException.typeError("." + name + " is not a function (called on " + jsTypeName(clazz) + ")");
        }
        try {
            return invoke(null, method, args);
        } catch (InvocationTargetException e) {
            Throwable cause = e.getCause();
            if (cause instanceof RuntimeException re) {
                throw re;
            }
            if (cause instanceof Error err) {
                throw err;
            }
            throw new RuntimeException(cause == null ? e.getMessage() : cause.getMessage(), cause);
        } catch (IllegalAccessException e) {
            throw JsErrorException.typeError("." + name + " is not accessible (on " + jsTypeName(clazz) + ")");
        }
    }

    static Object invoke(Object object, String name, Object[] args) {
        Method method = findMethod(object.getClass(), name, args);
        if (method == null) {
            throw JsErrorException.typeError("." + name + " is not a function (called on " + jsTypeName(object.getClass()) + ")");
        }
        try {
            return invoke(object, method, args);
        } catch (InvocationTargetException e) {
            // Unwrap so the underlying Java exception (and its message) reaches the caller
            // and can become a JS-catchable JsError at the host-function boundary.
            Throwable cause = e.getCause();
            if (cause instanceof RuntimeException re) {
                throw re;

View on GitHub (pinned to a22eb90246)