json-path/JsonPath · error · JsonException

Cannot create JSON iterator for " + value

Error message

Cannot create JSON iterator for " + value

What it means

createScope() in JakartaMappingProvider's JsonStructureToParserAdapter can only iterate JsonArray and JsonObject structures. If it is handed any other JsonValue (a scalar like JsonString, JsonNumber, JsonValue.TRUE/FALSE/NULL), it throws JsonException because no container iterator exists for scalars. This is called by the adapter constructor and by next() when advancing into nested values.

Solutions

  1. Wrap or normalize scalars before mapping — ensure the value passed to map/toJson is a JsonObject or JsonArray
  2. Refine the JsonPath so it returns a structure, or read scalar results directly instead of via the streaming adapter
  3. Catch JsonException and handle scalar results as leaf values in your code

Example fix

// before
Object doc = Json.createObjectBuilder().build();
JsonValue scalar = jsonPath.read(doc); // may be a JsonString
mapper.map(scalar, ...); // JsonException
// after
JsonValue scalar = jsonPath.read(doc);
if (scalar instanceof JsonStructure) {
    mapper.map(scalar, ...);
} else {
    Object v = unwrapScalar(scalar); // handle string/number/bool/null directly
}
Defensive patterns

Strategy: validation

Validate before calling

if (!(value instanceof JsonStructure)) {
    throw new IllegalArgumentException("Expected JsonObject or JsonArray, got: " + value.getValueType());
}

Type guard

boolean isIterableStructure(JsonValue v) {
    return v instanceof JsonArray || v instanceof JsonObject;
}

Try / catch

try {
    mapper.map(value, typeRef, config);
} catch (JsonException e) {
    // value was a scalar; unwrap or wrap it before mapping
}

Prevention

When it happens

Trigger: Driving the adapter with a root or nested JsonValue that is a scalar (string, number, true, false, null) rather than a JsonObject or JsonArray — e.g. mapping the result of a JSON-P query that selected a single scalar.

Common situations: A JsonPath expression like $.name or $[0] that resolves to a scalar is fed to the Jakarta mapping provider, which expects a JSON structure at the root; upgrading providers so a previously object/array root is now scalar.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of json-path/JsonPath@62a4c9f0f6 (2026-09-11). Data as JSON: /api/errors/63ac4ac1a84e28ca. Report an issue: GitHub.

Appendix: source

Thrown at json-path/src/main/java/com/jayway/jsonpath/spi/mapper/JakartaMappingProvider.java:545

                while (scope.hasNext()) {
                    scope.next();
                }
                state = Event.END_OBJECT;
            }
        }

        @Override
        public void close() {
            // JSON objects are read-only
        }

        private JsonStructureScope createScope(JsonValue value) {
            if (value instanceof JsonArray) {
                return new JsonArrayScope((JsonArray) value);
            } else if (value instanceof JsonObject) {
                return new JsonObjectScope((JsonObject) value);
            }
            throw new JsonException("Cannot create JSON iterator for " + value);
        }

        private Event getState(JsonValue value) {
            switch (value.getValueType()) {
            case ARRAY:
                return Event.START_ARRAY;
            case OBJECT:
                return Event.START_OBJECT;
            case STRING:
                return Event.VALUE_STRING;
            case NUMBER:
                return Event.VALUE_NUMBER;
            case TRUE:
                return Event.VALUE_TRUE;
            case FALSE:
                return Event.VALUE_FALSE;
            case NULL:
                return Event.VALUE_NULL;

View on GitHub (pinned to 62a4c9f0f6)