{"record":{"id":"64fd473468713f01","repo":"karatelabs/karate","slug":"assert-expression-must-return-boolean","errorCode":null,"errorMessage":"assert expression must return boolean: ","messagePattern":"assert expression must return boolean: ","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/core/StepExecutor.java","lineNumber":1905,"sourceCode":"    /**\n     * True for an expression like {@code ({ a: 1 })} or {@code ([1, 2])} — a JSON literal\n     * the user forced through JS evaluation by wrapping it in round brackets.\n     */\n    private static boolean isParenWrappedJson(String expr) {\n        if (expr.length() < 3 || expr.charAt(0) != '(' || expr.charAt(expr.length() - 1) != ')') {\n            return false;\n        }\n        return StringUtils.looksLikeJson(expr.substring(1, expr.length() - 1).trim());\n    }\n\n    private void executeAssert(Step step) {\n        Object result = runtime.eval(step.getText());\n        if (result instanceof Boolean b) {\n            if (!b) {\n                throw new AssertionError(withCommentLabel(step, \"assert failed: \" + step.getText()));\n            }\n        } else {\n            throw new RuntimeException(\"assert expression must return boolean: \" + step.getText());\n        }\n    }\n\n    private static final LogContext.LogWriter SCENARIO_LOG = LogContext.with(LogContext.SCENARIO_LOGGER);\n\n    private void executePrint(Step step) {\n        // Wrap in array to handle comma-separated expressions like: print 'foo', 'bar'\n        // Without wrapping, JS comma operator would return only the last value\n        Object value = runtime.eval(\"[\" + step.getText() + \"]\");\n        if (value instanceof List<?> list) {\n            StringBuilder sb = new StringBuilder();\n            for (int i = 0; i < list.size(); i++) {\n                if (i > 0) {\n                    sb.append(' ');\n                }\n                sb.append(StepUtils.stringify(list.get(i)));\n            }\n            SCENARIO_LOG.info(sb.toString());","sourceCodeStart":1887,"sourceCodeEnd":1923,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/core/StepExecutor.java#L1887-L1923","documentation":"Karate's 'assert' step requires its expression to evaluate to a boolean. If runtime.eval returns a non-Boolean (number, string, null, map), Karate throws this RuntimeException naming the offending expression, because the assertion result cannot be interpreted as pass/fail.","triggerScenarios":"An assert step whose expression yields a non-boolean value: 'assert response' (a map), 'assert someNumber', 'assert myString', or a function call returning a non-boolean.","commonSituations":"Assuming truthy/falsy JS semantics apply; asserting directly on response bodies or variables; calling a helper function that returns data instead of a comparison result.","solutions":["Wrap the expression in a comparison returning boolean: 'assert response.status != null'","If checking existence, use a boolean operator (e.g. 'assert karate.sizeOf(list) > 0')","Make helper functions return booleans, or compare their result explicitly","Use karate.match / match steps instead of raw asserts for structural checks"],"exampleFix":"// before: expression is a value, not boolean\nassert response\n// after\nassert response != null && response.id != null","handlingStrategy":"type-guard","validationCode":"// evaluate the expression and check its type before using assert semantics\nObject v = karate.eval(expression);\nboolean isBool = v instanceof Boolean;","typeGuard":"static boolean isBooleanResult(Object v) { return v instanceof Boolean; }","tryCatchPattern":"try { executor.execute(assertStep); } catch (RuntimeException e) { if (e.getMessage().startsWith(\"assert expression must return boolean\")) { throw new IllegalStateException(\"wrap expression in a comparison: \" + e.getMessage()); } throw e; }","preventionTips":["Always assert comparisons, not bare values","Make helper functions return booleans","Prefer match steps for structural checks"],"tags":["karate","assert","boolean","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}