karatelabs/karate · error · RuntimeException

Failed to evaluate dynamic expression

Error message

Failed to evaluate dynamic expression: ${templateScenario.getDynamicExpression()}

What it means

Karate wraps any exception thrown while evaluating a dynamic scenario expression in this RuntimeException, preserving the original as the cause. It signals that the expression itself failed to evaluate (syntax error, missing variable, thrown exception inside the called function), as opposed to returning a wrong type.

Solutions

  1. Inspect the cause exception in the stack trace to find the underlying JS/Java failure
  2. Verify all variables and functions referenced by the expression are defined in scope (def before the Examples)
  3. Run the expression's body as a normal '* def result = <expr>' step to reproduce the error in isolation
  4. Fix the underlying exception (missing def, wrong signature, missing class) and re-run

Example fix

// before (undefined helper)
Examples: karate.call('missing.feature')
// after
* def rows = call read('helpers.feature')
Examples: rows
Defensive patterns

Strategy: try-catch

Validate before calling

// reproduce the expression as a plain step first
* def __probe = <expression>

Type guard

null

Try / catch

try { evaluateDynamic(expression) } catch (RuntimeException e) { Throwable cause = e.getCause(); log.error('Dynamic expression failed: ' + cause, cause); throw e; }

Prevention

When it happens

Trigger: A dynamic expression in an Examples table throws during evaluation — undefined JS variable, a Java method that throws, malformed JS syntax, or a generator function raising an exception mid-iteration.

Common situations: Calling a helper defined in another feature that isn't in scope; a typo in a variable name inside the expression; a Java call whose signature changed; classpath missing for a Java class referenced by the expression.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


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

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/core/FeatureRuntime.java:753

                String expression = templateScenario.getDynamicExpression();
                Object result;
                try {
                    result = sr.eval(expression);
                } finally {
                    sr.releaseHttpClient();
                }

                if (result instanceof List) {
                    return (List<?>) result;
                } else if (result instanceof JavaCallable) {
                    // Generator function - call repeatedly until null/non-map
                    return evaluateGeneratorFunction(result);
                } else {
                    // Expression didn't return a list or function - error
                    throw new RuntimeException("Dynamic expression must return a list or function: " + expression + ", got: " + (result != null ? result.getClass().getName() : "null"));
                }
            } catch (Exception e) {
                throw new RuntimeException("Failed to evaluate dynamic expression: " + templateScenario.getDynamicExpression(), e);
            }
        }

        /**
         * Evaluates a generator function by calling it repeatedly with incrementing index
         * until it returns null or a non-Map value.
         */
        @SuppressWarnings("unchecked")
        private List<Map<String, Object>> evaluateGeneratorFunction(Object function) {
            List<Map<String, Object>> results = new ArrayList<>();
            JavaCallable callable = (JavaCallable) function;
            int index = 0;

            while (true) {
                Object rowValue;
                try {
                    // JsCallable.call() works with null context (uses declared context internally)
                    rowValue = callable.call(null, index);

View on GitHub (pinned to a22eb90246)