karatelabs/karate · error · java.util.NoSuchElementException
NoSuchElementException
Error message
NoSuchElementException
What it means
JsObject's property iterator throws NoSuchElementException when next() is called after all own properties have been yielded (peeked exhausted and advance() false). Properties are read lazily at yield time so callback-driven mutations propagate, which makes over-advancing this iterator especially easy to trigger from user callbacks.
Solutions
- Guard next() with hasNext() in Java; in JS rely on the done flag.
- Avoid add/delete of properties during enumeration, or iterate over a snapshot of keys.
- Do not re-enter or share the iterator from inside the iteration callback.
- Upgrade karate-js if triggered by library-internal enumeration.
Example fix
// before
while (true) { KeyValue kv = it.next(); ... }
// after
while (it.hasNext()) { KeyValue kv = it.next(); ... } Defensive patterns
Strategy: try-catch
Validate before calling
if (obj == null) return; // no properties to enumerate
Type guard
boolean canAdvance(Iterator<?> it) { return it != null && it.hasNext(); } Try / catch
try { while (it.hasNext()) { KeyValue kv = it.next(); } } catch (NoSuchElementException e) { log.warn("property iterator over-advanced", e); } Prevention
- Avoid mutating the object (add/delete properties) from inside enumeration callbacks.
- Enumerate a snapshot of Object.keys when mutation is unavoidable.
- Don't re-enter or share the property iterator across nested loops.
- Keep property iteration in for...of/for...in constructs, which respect done/hasNext.
When it happens
Trigger: Advancing the object property iterator past the last key; an enumeration loop (for...in, Object.entries internals) whose callback deletes/adds properties or re-enters the iterator.
Common situations: JS callbacks that mutate the object being enumerated; deep-equal/clone helpers iterating properties; host Java code consuming the iterator without hasNext().
Related errors
- NoSuchElementException
- NoSuchElementException
- NoSuchElementException
- NoSuchElementException
- NoSuchElementException
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/13ab0f3b74e5212d.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsObject.java:1096
// {entries,values}/getter-making-future-key-nonenumerable).
if (s.tombstoned) continue;
if (!isEnumerable(s.name)) continue;
peeked = s;
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();
}
PropertySlot s = peeked;
peeked = null;
// Read at yield time so callback-driven mutations before
// the next next() call propagate. With ctx, accessor slots
// resolve via getter invocation; without ctx, they surface
// as null (Java-interop semantic).
Object v = ctx != null
? s.read(JsObject.this, ctx)
: s instanceof DataSlot ds ? ds.value : null;
return new KeyValue(JsObject.this, index++, s.name, v);
}
};
}
/** Non-tombstoned slots in §9.1.11.1 ordering — integer-index slots
* ascending, then named slots in insertion order. Backs
* {@link #jsEntries(CoreContext)}; the enumerable filter is applied atView on GitHub (pinned to a22eb90246)