karatelabs/karate · error · java.util.NoSuchElementException
NoSuchElementException
Error message
NoSuchElementException
What it means
JsGlobalThis's property iterator (used to enumerate the global object's bindings) throws NoSuchElementException when next() is called after the last entry. Like the other JS iterators, callers must consult hasNext() first; the exception signals iteration past the end of the global-object entry set.
Solutions
- Always pair next() with hasNext() (or a for-each loop).
- Get a fresh iterator for each enumeration pass.
- Avoid mutating the global object while enumerating it; collect keys first, then mutate.
- If thrown from library internals during global enumeration, report with a repro; upgrade karate-js.
Example fix
// before
KeyValue kv = it.next(); // assumes another entry exists
// after
if (it.hasNext()) { KeyValue kv = it.next(); } Defensive patterns
Strategy: type-guard
Type guard
boolean canAdvance(Iterator<?> it) { return it != null && it.hasNext(); } Try / catch
try { KeyValue kv = it.next(); } catch (NoSuchElementException e) { /* exhausted: treat as end of enumeration */ } Prevention
- Use hasNext()-guarded loops for global-object enumeration.
- Collect global keys into a list first, then iterate the snapshot.
- Do not define/delete globals during enumeration.
- Allocate a fresh iterator per enumeration pass.
When it happens
Trigger: Advancing the globalThis entry iterator past its final key; internal enumeration loops (for...in / Object.keys style) driven by buggy or duplicated consumption of the same iterator.
Common situations: Host Java code enumerating global variables; engine bugs when globals are added/removed mid-enumeration; iterating after a prior full pass without resetting.
Related errors
- NoSuchElementException
- NoSuchElementException
- NoSuchElementException
- NoSuchElementException
- NoSuchElementException
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/90cf3106a10fb7aa.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsGlobalThis.java:243
if (bindings().isTombstoned(e.getKey())) continue;
if (isEnumerable(e.getKey())) {
peeked = e;
return true;
}
}
peeked = null;
return false;
}
@Override
public boolean hasNext() {
return peeked != null || advance();
}
@Override
public KeyValue next() {
if (peeked == null && !advance()) {
throw new NoSuchElementException();
}
Map.Entry<String, Object> entry = peeked;
peeked = null;
return new KeyValue(JsGlobalThis.this, index++, entry.getKey(), entry.getValue());
}
};
}
@Override
public Map<String, Object> toMap() {
// Raw view of the unified store — both visible and hidden entries,
// identity preserved (no JsFunction → JsFunctionWrapper). Built-ins
// not yet lazy-cached aren't here; Object.keys(globalThis) only sees
// realized entries (and gets filtered down further by enumerability
// via getOwnAttrs above). Merge in any JsObject.props entries — those
// hold accessor descriptors installed via Object.defineProperty(this, …)
// (BindingSlot is data-only).
Map<String, Object> raw = bindings().getRawMap();View on GitHub (pinned to a22eb90246)