karatelabs/karate · error · JsErrorException

is not iterable

Error message

 is not iterable

What it means

Array.from falls back to an array-like length-walk only when appropriate; if the source has no @@iterator and is not array-like, this TypeError names the value and states it is not iterable. Per spec, values without an iterator protocol and without length cannot be converted to arrays.

Solutions

  1. Wrap the value: use Object.values(obj) or Object.entries(obj) for plain objects
  2. Make the source iterable by implementing @@iterator, or spread a real array
  3. Guard with a check that the value has Symbol.iterator or a numeric length before calling Array.from

Example fix

// before
Array.from(config); // plain object -> not iterable
// after
Array.from(Object.values(config));
Defensive patterns

Strategy: type-guard

Validate before calling

function isIterable(x) { return x != null && typeof x[Symbol.iterator] === 'function'; }

Type guard

function isIterable(x) { return x != null && typeof x[Symbol.iterator] === 'function'; }

Try / catch

try { var a = Array.from(src); } catch (e) { if (String(e).indexOf('is not iterable') !== -1) { a = Object.values(src || {}); } else { throw e; } }

Prevention

When it happens

Trigger: Array.from({a:1}) (plain object, no length, no iterator); Array.from(42); Array.from(true); Array.from on a custom object that lacks Symbol.iterator.

Common situations: Assuming all objects are array-like; iterating over a map-like structure without converting it; passing class instances that never implemented the iterable interface.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/js/JsArrayConstructor.java:98

                index++;
            }
            // Spec §23.1.2.1 returns an Array exotic — wrap so
            // `Array.from(...).constructor === Array` and
            // `Array.from(...) instanceof Array` hold.
            return new JsArray(results);
        }
        // Array-like fallback: map-of-string-keys with `length` (e.g. {0: 'a', 1: 'b', length: 2}).
        if (source instanceof Map) {
            JsArray array = JsArray.toArray((Map<String, Object>) source);
            int index = 0;
            for (Object v : array.list) {
                Object mapped = mapFn == null ? v : mapFn.call(context, new Object[]{v, index});
                results.add(mapped);
                index++;
            }
            return new JsArray(results);
        }
        throw JsErrorException.typeError(source + " is not iterable");
    }

    private Object isArray(Object[] args) {
        return args.length > 0 && args[0] instanceof List;
    }

    private Object of(Object[] args) {
        // Spec §23.1.2.3 — return an Array. Wrap in JsArray (mutable copy)
        // so callers can {@code push}/{@code pop} and so
        // {@code Array.of(...).constructor === Array} holds; the bare
        // {@code Arrays.asList} would be a fixed-size Java List.
        List<Object> list = new ArrayList<>(args.length);
        for (Object arg : args) list.add(arg);
        return new JsArray(list);
    }

}

View on GitHub (pinned to a22eb90246)