{"record":{"id":"112f978deb5f2455","repo":"json-path/JsonPath","slug":"cannot-iterate-over","errorCode":null,"errorMessage":"Cannot iterate over ","messagePattern":"Cannot iterate over ","errorType":"exception","errorClass":"JsonPathException","httpStatus":null,"severity":"error","filePath":"json-path/src/main/java/com/jayway/jsonpath/spi/json/AbstractJsonProvider.java","lineNumber":171,"sourceCode":"        } else if(obj instanceof String){\n            return ((String)obj).length();\n        }\n        throw new JsonPathException(\"length operation cannot be applied to \" + (obj != null ? obj.getClass().getName()\n                : \"null\"));\n    }\n\n    /**\n     * Converts given array to an {@link Iterable}\n     *\n     * @param obj an array\n     * @return an Iterable that iterates over the entries of an array\n     */\n    @SuppressWarnings(\"unchecked\")\n    public Iterable<?> toIterable(Object obj) {\n        if (isArray(obj))\n            return ((Iterable) obj);\n        else\n            throw new JsonPathException(\"Cannot iterate over \" + obj!=null?obj.getClass().getName():\"null\");\n    }\n\n    @Override\n    public Object unwrap(Object obj) {\n        return obj;\n    }\n\n}\n","sourceCodeStart":153,"sourceCodeEnd":180,"githubUrl":"https://github.com/json-path/JsonPath/blob/62a4c9f0f65ba3f625aa0867d64c528ba72d09ec/json-path/src/main/java/com/jayway/jsonpath/spi/json/AbstractJsonProvider.java#L153-L180","documentation":"AbstractJsonProvider.toIterable converts a JSON array into an Iterable so paths can be iterated. Only arrays support iteration; passing any other node type (object, string, number, null) throws JsonPathException. The message also suffers an operator-precedence bug ('+' before '!='), possibly printing wrong class info, but the cause is a non-array target.","triggerScenarios":"Evaluating wildcard/iterate paths like $[*] or $.items[*] where the node is not an array; calling jsonProvider.toIterable(obj) directly on a Map/String; using walk/forEach-style JsonPath APIs over a scalar node.","commonSituations":"Iterating a field that is an object in some responses and an array in others; iterating null fields; deep-scan ..[*] paths crossing primitive nodes the developer assumed were arrays.","solutions":["Ensure the node is an array before iterating (check isArray(obj))","Correct the path: use .* or property access for objects instead of [*]","Null/type-check the resolved node before iteration and handle the non-array case explicitly","Wrap evaluation in try-catch for JsonPathException when document shape is uncertain"],"exampleFix":"// before\nfor (Object o : provider.toIterable(node)) { ... } // throws if node is a Map\n// after\nif (provider.isArray(node)) {\n    for (Object o : provider.toIterable(node)) { ... }\n} else if (provider.isMap(node)) {\n    for (Object o : provider.getPropertyKeys(node)) { ... }\n}","handlingStrategy":"type-guard","validationCode":"if (!provider.isArray(node)) throw new IllegalArgumentException(\"expected JSON array, got: \" + (node == null ? \"null\" : node.getClass()));","typeGuard":"boolean isArray(Object o) { return o instanceof Iterable; }","tryCatchPattern":"try {\n    for (Object o : provider.toIterable(node)) { handle(o); }\n} catch (JsonPathException e) {\n    // node was not an array\n}","preventionTips":["Use [*] only on nodes guaranteed to be arrays","Use .* for object nodes instead of [*]","Check isArray before iterating","Defensively handle fields whose type varies across API versions"],"tags":["json-path","iteration","unsupported-operation"],"backgroundTag":"unsupported-operation","analyzedSha":"62a4c9f0f65ba3f625aa0867d64c528ba72d09ec","analyzedAt":"2026-09-11T11:36:00.448Z","contentChangedAt":"2026-09-11T11:36:00.448Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}