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
- Inspect the cause exception in the stack trace to find the underlying JS/Java failure
- Verify all variables and functions referenced by the expression are defined in scope (def before the Examples)
- Run the expression's body as a normal '* def result = <expr>' step to reproduce the error in isolation
- 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
- Define all variables/functions used by the expression before the Examples table
- Test the expression standalone as a '* def' step while developing
- Keep Java helpers called by expressions stable and on the test classpath
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
- Dynamic expression must return a list or function
- Unable to resolve global `this`
- Invalid ignore
- karate-boot.js evaluation failed
- doc() requires 'read' key with template path
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)