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

  1. Inspect the value printed in the message and fix the actual data source so it yields a number
  2. Coerce the operand explicitly before matching (e.g. Integer.parseInt/Double.parseDouble for strings)
  3. Add a preceding type/shape assertion (Match.that(x).isTypeOf("number")) to fail earlier with a clearer message
  4. 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

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


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)