karatelabs/karate · error · ParserException
continue label does not name a loop
Error message
continue label does not name a loop: ${target} What it means
`continue` may only target labels that name iteration statements (loops). After confirming the label exists in scope, labelNodeChecks re-checks with the iteration flag (Label.contains(labels, target, true)); if the label names a non-loop labeled statement (e.g. a labeled block or switch), this early error is thrown.
Solutions
- Change `continue label;` to `break label;` if the target is a non-loop labeled statement and you want to exit it
- Retarget continue to a label that names an enclosing loop
- Restructure the non-loop labeled statement into a loop if iteration semantics are intended
Example fix
// before
blk: { continue blk; }
// after
blk: { break blk; } Defensive patterns
Strategy: validation
Validate before calling
// Verify continue targets label loops, not blocks/switch: const cont = [...src.matchAll(/continue\s+([A-Za-z_$][\w$]*)/g)].map(m=>m[1]); const loopLabels = new Set([...src.matchAll(/([A-Za-z_$][\w$]*):\s*(?:for|while|do)\b/g)].map(m=>m[1])); const bad = cont.filter(t => !loopLabels.has(t));
Try / catch
try { eval(js); } catch (e) { if (String(e).includes('continue label does not name a loop')) { /* switch to `break label` or retarget a loop label */ } throw e; } Prevention
- Only label loops if you plan to `continue` them; use `break` for blocks
- Convert labeled blocks to loops when iteration semantics are needed
- Review label usage after converting loops to plain blocks
When it happens
Trigger: `continue blockLabel;` where blockLabel labels a plain block `{ }`, an `if`, or a `switch` rather than a for/while/do loop — e.g. `blk: { continue blk; }`.
Common situations: Changing a loop into a labeled block while keeping a continue pointing at it; misunderstanding that `continue` (unlike `break`) cannot target arbitrary labeled statements.
Related errors
- continue references an undefined label
- label already in scope
- break references an undefined label
- unexpected logical-assignment operator
- unexpected operator
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/29520bb2232245ca.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/parser/JsParser.java:425
// §15.7.1 makes a static initialization block a boundary of the same kind
// as a function body: nothing inside it may name a label outside it.
case FN_EXPR, FN_ARROW_EXPR, CLASS_STATIC_BLOCK -> {
return null;
}
case BREAK_STMT -> {
String target = labelReference(node);
if (target != null && !Label.contains(labels, target, false)) {
throw new ParserException("break references an undefined label: " + target);
}
}
case CONTINUE_STMT -> {
String target = labelReference(node);
if (target != null) {
if (!Label.contains(labels, target, false)) {
throw new ParserException("continue references an undefined label: " + target);
}
if (!Label.contains(labels, target, true)) {
throw new ParserException("continue label does not name a loop: " + target);
}
}
}
default -> {
}
}
return labels;
}
/** The label named by a {@code break} / {@code continue}, or null when it has none —
* children are [keyword] or [keyword, label]. */
private static String labelReference(Node node) {
return node.size() > 1 ? node.get(1).getText() : null;
}
/** True if the labelled item — after peeling any stacked labels, since {@code a: b: for}
* makes both names loop labels — is an iteration statement. */
private static boolean labelsIterationStatement(Node labelled) {View on GitHub (pinned to a22eb90246)