karatelabs/karate · error · ParserException
'break' may not cross a class static initialization block
Error message
'break' may not cross a class static initialization block
What it means
An unlabeled `break` inside a class static initialization block has no enclosing loop or switch to target (the block does not count), so it is an early error. The Karate JS parser throws this when a bare BREAK_STMT (no label) is found in a static block outside any nested function, loop, or switch (SB_FN | SB_LOOP | SB_SWITCH flags unset).
Solutions
- Remove the stray `break` and restructure the condition (`if (cond) { ... }` around the rest).
- Wrap the breakable logic in an actual loop or switch, or in a nested function using `return`.
- If exiting early from a labeled construct, ensure the label refers to a loop/switch inside the block.
Example fix
// before
class C { static { for (const x of xs) { if (x.bad) break; use(x); } } } // OK
// before (invalid)
class C { static { if (!ready) break; init(); } }
// after
class C { static { if (ready) init(); } } Defensive patterns
Strategy: validation
Validate before calling
// flag unlabeled break in static block source outside loops/switches (naive scan)
function noBareBreak(src) { return !/(^|[{;\s])break\s*[;}]/.test(src); } Try / catch
try { karate.eval(blockSrc); } catch (e) { if (String(e).includes("'break' may not cross a class static initialization block")) { /* restructure control flow */ } } Prevention
- Only use `break` inside loops or switches, even in static blocks.
- Replace desired early exits with guarded `if` blocks.
- When converting function/IIFE bodies to static blocks, rewrite all control-flow exits.
When it happens
Trigger: Parsing `class C { static { break; } }` or any unlabeled `break` in a static block not inside a nested `for`/`while`/`switch`/function.
Common situations: Copy-pasting loop-exit code into a static initializer; replacing `return` with `break` after hitting the return restriction; breaking out of a block body expecting C-style `break` semantics.
Related errors
- 'await' is a reserved word in a class static initialization…
- 'return' is not allowed in a class static initialization…
- parser state: [ ]
- optional chain is not a valid assignment target
- unary expression cannot be the base of '**'; wrap it in…
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/9b53127ed0931177.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/parser/JsParser.java:700
// `x.await` / `x?.await` name a member, they do not reference one
if (keepAwait && type == IDENT && prev != DOT && prev != QUES_DOT
&& isIdentText(child.token, "await")) {
throw new ParserException("'await' is a reserved word in a class static initialization block");
}
prev = type;
continue;
}
prev = null;
int childFlags = flags;
switch (child.type) {
case RETURN_STMT -> {
if ((flags & SB_FN) == 0) {
throw new ParserException("'return' is not allowed in a class static initialization block");
}
}
case BREAK_STMT -> {
if ((flags & (SB_FN | SB_LOOP | SB_SWITCH)) == 0 && child.size() == 1) {
throw new ParserException("'break' may not cross a class static initialization block");
}
}
case CONTINUE_STMT -> {
if ((flags & (SB_FN | SB_LOOP)) == 0 && child.size() == 1) {
throw new ParserException("'continue' may not cross a class static initialization block");
}
}
case FOR_STMT, WHILE_STMT, DO_WHILE_STMT -> childFlags |= SB_LOOP;
case SWITCH_STMT -> childFlags |= SB_SWITCH;
case FN_EXPR, FN_ARROW_EXPR -> childFlags |= SB_FN;
default -> {
}
}
// A function's parameters are [~Await] along with its body; an arrow's are
// not — only the body (always its last child) leaves the reserved region.
if (node.type == NodeType.FN_EXPR
|| (node.type == NodeType.FN_ARROW_EXPR && i == last)) {
childFlags |= SB_AWAIT_OK;View on GitHub (pinned to a22eb90246)