{"record":{"id":"13ab0f3b74e5212d","repo":"karatelabs/karate","slug":"nosuchelementexception-jsobject","errorCode":null,"errorMessage":"NoSuchElementException","messagePattern":"NoSuchElementException","errorType":"exception","errorClass":"java.util.NoSuchElementException","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/JsObject.java","lineNumber":1096,"sourceCode":"                    // {entries,values}/getter-making-future-key-nonenumerable).\n                    if (s.tombstoned) continue;\n                    if (!isEnumerable(s.name)) continue;\n                    peeked = s;\n                    return true;\n                }\n                peeked = null;\n                return false;\n            }\n\n            @Override\n            public boolean hasNext() {\n                return peeked != null || advance();\n            }\n\n            @Override\n            public KeyValue next() {\n                if (peeked == null && !advance()) {\n                    throw new NoSuchElementException();\n                }\n                PropertySlot s = peeked;\n                peeked = null;\n                // Read at yield time so callback-driven mutations before\n                // the next next() call propagate. With ctx, accessor slots\n                // resolve via getter invocation; without ctx, they surface\n                // as null (Java-interop semantic).\n                Object v = ctx != null\n                        ? s.read(JsObject.this, ctx)\n                        : s instanceof DataSlot ds ? ds.value : null;\n                return new KeyValue(JsObject.this, index++, s.name, v);\n            }\n        };\n    }\n\n    /** Non-tombstoned slots in §9.1.11.1 ordering — integer-index slots\n     *  ascending, then named slots in insertion order. Backs\n     *  {@link #jsEntries(CoreContext)}; the enumerable filter is applied at","sourceCodeStart":1078,"sourceCodeEnd":1114,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/JsObject.java#L1078-L1114","documentation":"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.","triggerScenarios":"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.","commonSituations":"JS callbacks that mutate the object being enumerated; deep-equal/clone helpers iterating properties; host Java code consuming the iterator without hasNext().","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."],"exampleFix":"// before\nwhile (true) { KeyValue kv = it.next(); ... }\n// after\nwhile (it.hasNext()) { KeyValue kv = it.next(); ... }","handlingStrategy":"try-catch","validationCode":"if (obj == null) return; // no properties to enumerate","typeGuard":"boolean canAdvance(Iterator<?> it) { return it != null && it.hasNext(); }","tryCatchPattern":"try { while (it.hasNext()) { KeyValue kv = it.next(); } } catch (NoSuchElementException e) { log.warn(\"property iterator over-advanced\", e); }","preventionTips":["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."],"tags":["javascript","iterator","object"],"backgroundTag":"index-out-of-bounds","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-16T19:17:19.609Z"}