karatelabs/karate · error · RuntimeException
expected number instead of:
Error message
expected number instead of:
What it means
The match Operation engine coerces match operands to BigDecimal for numeric comparisons. When the operand is neither a String parseable as a number nor any Number type (Long/Integer/Short/Byte/other Number), it throws 'expected number instead of: <value>'. The library throws because a numeric operation received a non-numeric value.
Solutions
- Inspect the value printed in the message and fix the actual data source so it yields a number
- Coerce the operand explicitly before matching (e.g. Integer.parseInt/Double.parseDouble for strings)
- Add a preceding type/shape assertion (Match.that(x).isTypeOf("number")) to fail earlier with a clearer message
- If the value can be null, guard the comparison with a null check before invoking the numeric match
Example fix
// before
Match.that(response.count).isGreaterThan("ten"); // non-numeric operand
// after
Match.that(Integer.parseInt(response.count)).isGreaterThan(10); Defensive patterns
Strategy: validation
Validate before calling
if (!(operand instanceof Number) && !(operand instanceof String s && s.matches("-?\\d+(\\.\\d+)?"))) {
throw new IllegalArgumentException("numeric match needs a number, got: " + operand);
} Type guard
static boolean isNumeric(Object o) {
return o instanceof Number || (o instanceof String s && s.matches("-?\\d+(\\.\\d+)?"));
} Try / catch
try {
Match.that(actual).isGreaterThan(0);
} catch (RuntimeException e) {
if (e.getMessage().startsWith("expected number instead of")) {
// coerce or skip numeric assertion
}
} Prevention
- Coerce JSON string fields to numbers before numeric matches
- Null-check optional fields before comparisons
- Add isTypeOf("number") assertions upstream
When it happens
Trigger: Invoking numeric match operations (e.g. greaterThan/lessThan-style comparisons, arithmetic within match macros) with an actual or expected value that is a Map, List, boolean, or null instead of a number or numeric string.
Common situations: Comparing a JSON field that is sometimes null, comparing against an array element that turned out to be an object, or passing a boolean/string like 'true' where a number was expected in match expressions.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- assert expression must return boolean:
- boot.ext(' '): does not implement io.karatelabs.core.Ext
- cache() second argument must be a function:
- call expression must resolve to a feature path:
- cannot set xpath on non-XML variable:
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/659efb38b25a0f98.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/match/Operation.java:811
mo.execute();
return mo.pass;
default:
throw new RuntimeException("unexpected type (match within): " + actual.type);
}
}
private static BigDecimal toBigDecimal(Object o) {
if (o instanceof BigDecimal bd) {
return bd;
} else if (o instanceof BigInteger bi) {
return new BigDecimal(bi);
} else if (o instanceof Long || o instanceof Integer || o instanceof Short || o instanceof Byte) {
// integral types convert exactly, going via doubleValue() would lose bits beyond 2^53
return BigDecimal.valueOf(((Number) o).longValue());
} else if (o instanceof Number n) {
return BigDecimal.valueOf(n.doubleValue());
} else {
throw new RuntimeException("expected number instead of: " + o);
}
}
boolean pass() {
pass = true;
return true;
}
boolean fail(String reason) {
pass = false;
if (reason == null) {
return false;
}
failReason = failReason == null ? reason : reason + " | " + failReason;
context.root.failures.add(this);
return false;
}
View on GitHub (pinned to a22eb90246)