karatelabs/karate · error · JsErrorException (typeError)
cannot apply post inc/dec to
Error message
cannot apply post inc/dec to: ${node} What it means
A TypeError thrown when a post-increment/decrement operator is applied to a node type that is not a variable reference or property access. Literal and other unexpected node shapes reach the switch's default arm; literals themselves are handled as no-ops ((x)++ returns the value unchanged), so this error signals a truly unsupported LHS form.
Solutions
- Rewrite so the increment target is a variable or property: `obj.count++`
- Assign the expression result to a variable first, then increment the variable
- Check for parser/interpreter version mismatches if the source looks valid
Example fix
// before (a + b)++; // after let s = a + b; s++;
Defensive patterns
Strategy: validation
Validate before calling
// Reject increment/decrement on non-assignable expressions
if (/\+\+\s*[^A-Za-z_$([]|--[^A-Za-z_$([]/.test(code)) { /* flag invalid target */ } Type guard
function isIncDecTarget(node) {
return node && ['Identifier','MemberExpression'].includes(node.type);
} Prevention
- Never write `expr++` where expr is a call, literal, or parenthesized binary expression
- Parse generated code and validate increment targets
- Keep parser and interpreter versions aligned
When it happens
Trigger: Executing `expr++` where expr parses as neither REF_EXPR, REF_DOT_EXPR, REF_BRACKET_EXPR, nor LIT_EXPR — e.g. `(a, b)++`, assignment to a call, or a malformed AST from a parser bug.
Common situations: Generated or transpiled code emitting invalid increment targets; hand-written JS like `foo()++`; engine version mismatch between parser and interpreter.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- cannot apply compound assignment to
- cannot apply logical-assignment to
- cannot apply pre inc/dec to
- cannot get from
- cannot set on
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/76c72af8da96dcc4.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/PropertyAccess.java:563
yield oldValue;
}
yield incDecRefByName(node, context, isIncrement, false);
}
case REF_DOT_EXPR, REF_BRACKET_EXPR -> {
AccessSite site = resolveWriteSite(node, context);
if (site == null || site == SHORT_CIRCUIT_SITE) yield Terms.UNDEFINED;
if (site.privateName != null) yield privateIncDec(site, isIncrement, false, context);
if (site.receiver != null) yield superIncDec(site, isIncrement, false, context);
yield site.isIndex
? postIncDecByIndex(site.target, site.key, isIncrement, context)
: postIncDecByName(site.target, (String) site.key, isIncrement, context);
}
case LIT_EXPR -> {
// Handle literals like (x)++ where x is wrapped
Object oldValue = Interpreter.eval(node, context);
yield oldValue; // Can't actually modify a literal result
}
default -> throw JsErrorException.typeError("cannot apply post inc/dec to: " + node);
};
}
/**
* Pre-increment/decrement: updates variable, returns new value.
*/
static Object preIncDec(Node node, CoreContext context, boolean isIncrement) {
return switch (node.type) {
case REF_EXPR -> {
int slot = node.slot;
Object[] frame;
if (slot >= 0 && (frame = context.frame) != null && frame[slot] != SlotTable.UNDECLARED) {
Object oldValue = frame[slot];
if (oldValue == SlotTable.TDZ) {
throw SlotTable.tdzError(node.getText());
}
Object step = Terms.incDecStep(oldValue);
Object newValue = isIncrement ? Terms.add(oldValue, step, context) : Terms.min(oldValue, step, context);View on GitHub (pinned to a22eb90246)