karatelabs/karate · error · ParserException
unary expression cannot be the base of '**'; wrap it in…
Error message
unary expression cannot be the base of '**'; wrap it in parentheses
What it means
The exponentiation operator `**` forbids a unary expression as its left operand (`-a ** 2` is an early error in JS to avoid ambiguity with `-(a ** 2)`). The Karate JS parser throws this when the base of a `**` expression is a unary/typeof/delete/await/minus-prefixed expression. Wrap the operand in parentheses to state intent.
Solutions
- Add parentheses: `(-x) ** 2` if you want the negated base, or `-(x ** 2)` if you want negation of the power.
- For `await`, use `(await p) ** 2`.
- For `typeof`/`delete` bases, restructure — they rarely make sense as exponent bases.
Example fix
// before let area = -r ** 2; // after let area = (-r) ** 2; // or -(r ** 2)
Defensive patterns
Strategy: validation
Validate before calling
// flag unary bases under **
function hasUnaryBase(src) { return /(^|[\s(])[+-]\s*[\w$.]+\s*\*\*/.test(src); } Try / catch
try { karate.eval(expr); } catch (e) { if (String(e).includes("cannot be the base of '**'")) { /* add parentheses */ } } Prevention
- Always parenthesize the base of `**` when it involves unary operators.
- Remember `-x ** 2` is illegal in JS even though `-x * x` is fine.
- Prefer `Math.pow(x, 2)` for negated bases to avoid precedence confusion.
When it happens
Trigger: Parsing expressions like `-x ** 2`, `+y ** 2`, `typeof a ** b`, `await p ** 2`, `delete o.k ** 2`, detected in earlyErrorNodeChecks for MATH_EXPR (power) nodes with a unary base.
Common situations: Porting math code like `-x ** 2` from Python (where it means `(-x) ** 2`) into JS; writing physics formulas with negated bases; code written by authors expecting C-like unary precedence.
Related errors
- parser state: [ ]
- optional chain is not a valid assignment target
- optional chain cannot be the operand of postfix ++/--
- optional chain cannot be the operand of prefix ++/--
- tagged template literal cannot follow an optional chain
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/11bba23a504afd02.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/parser/JsParser.java:514
TokenType op = node.size() > 1 && node.get(1).isToken() ? node.get(1).token.type : null;
boolean noCallCarveOut = op == PIPE_PIPE_EQ || op == AMP_AMP_EQ || op == QUES_QUES_EQ;
checkSimpleAssignmentTarget(lhs, "assignment target", noCallCarveOut);
}
}
case MATH_EXP_EXPR -> {
// §13.6: the base of `**` must be an UpdateExpression — an
// unparenthesized unary (-x, !x, ~x, +x, void x, typeof x,
// delete x.y, await x) is a SyntaxError; ++x / --x are legal.
Node base = stripExprWrappers(node.size() > 0 ? node.getFirst() : null);
if (base != null) {
boolean unaryBase = switch (base.type) {
case DELETE_EXPR, TYPEOF_EXPR, UNARY_EXPR, AWAIT_EXPR -> true;
case MATH_PRE_EXPR -> base.size() > 0 && base.getFirst().isToken()
&& (base.getFirst().token.type == PLUS || base.getFirst().token.type == MINUS);
default -> false;
};
if (unaryBase) {
throw new ParserException("unary expression cannot be the base of '**'; wrap it in parentheses");
}
}
}
case MATH_POST_EXPR -> {
// children: [operand, ++/--]
if (node.size() > 0) {
Node operand = node.getFirst();
if (sawOptionalChain && subtreeContainsOptionalChain(operand)) {
throw new ParserException("optional chain cannot be the operand of postfix ++/--");
}
checkSimpleAssignmentTarget(operand, "operand of postfix update", false);
}
}
case MATH_PRE_EXPR -> {
// children: [op, operand] — only ++/-- need a valid update target;
// unary +/- have no assignment side and parse the same shape.
if (node.size() > 1) {
Node op = node.getFirst();View on GitHub (pinned to a22eb90246)