karatelabs/karate · error · ParserException

'return' is not allowed in a class static initialization…

Error message

'return' is not allowed in a class static initialization block

What it means

`return` cannot appear in a class static initialization block — the block is not a function, so there is nothing to return from. The Karate JS parser throws this when a RETURN_STMT is found while walking a static-block body without the SB_FN (inside-nested-function) flag.

Solutions

  1. Remove the `return` and express the early exit with `if`/`throw` around the remaining statements.
  2. Wrap the logic in a static method or nested function where `return` is valid: `static { init(); }`.
  3. Use a labeled block with `break` if you need an early exit to the end of the block.

Example fix

// before
class C { static { if (!ready) return; setup(); } }
// after
class C { static { if (ready) setup(); } }
Defensive patterns

Strategy: validation

Validate before calling

// flag top-level return in static block source (naive: any return not inside a nested function)
function noBareReturn(src) { return !/(^|[{;\s])return\b/.test(src.replace(/function[^{]*\{[\s\S]*?\}/g, '')); }

Try / catch

try { karate.eval(blockSrc); } catch (e) { if (String(e).includes("'return' is not allowed")) { /* replace with if/throw control flow */ } }

Prevention

When it happens

Trigger: Parsing `class C { static { return x; } }` — a return statement directly inside a static block (returns inside nested functions within the block are fine).

Common situations: Converting an IIFE or constructor body into a static block and keeping its `return`; copy-pasting function code into a static initializer; early-exit patterns carried over from function bodies.

Related errors


AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/fff1ea54f076d48a. Report an issue: GitHub.

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/parser/JsParser.java:695

        TokenType prev = null;
        for (int i = 0; i <= last; i++) {
            Node child = node.get(i);
            if (child.isToken()) {
                TokenType type = child.token.type;
                // `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 -> {
                }
            }

View on GitHub (pinned to a22eb90246)