json-path/JsonPath · error · InvalidModificationException

Can only add to an array

Error message

Can only add to an array

What it means

PathRef.add() appends a value to the JSON array located by an index-based path. Jayway JsonPath only supports the 'add' mutation when the target element is an array; if the element resolved at [parent, index] is a map, scalar, or null-like invalid value it is not silently converted, so the library throws InvalidModificationException("Can only add to an array").

Source

Thrown at json-path/src/main/java/com/jayway/jsonpath/internal/PathRef.java:181

        public void convert(MapFunction mapFunction, Configuration configuration){
            Object currentValue = configuration.jsonProvider().getArrayIndex(parent, index);
            configuration.jsonProvider().setArrayIndex(parent, index, mapFunction.map(currentValue, configuration));
        }

        public void delete(Configuration configuration){
            configuration.jsonProvider().removeProperty(parent, index);
        }

        public void add(Object value, Configuration configuration){
            Object target = configuration.jsonProvider().getArrayIndex(parent, index);
            if(targetInvalid(target)){
                return;
            }
            if(configuration.jsonProvider().isArray(target)){
                configuration.jsonProvider().setProperty(target, null, value);
            } else {
                throw new InvalidModificationException("Can only add to an array");
            }
        }

        public void put(String key, Object value, Configuration configuration){
            Object target = configuration.jsonProvider().getArrayIndex(parent, index);
            if(targetInvalid(target)){
                return;
            }
            if(configuration.jsonProvider().isMap(target)){
                configuration.jsonProvider().setProperty(target, key, value);
            } else {
                throw new InvalidModificationException("Can only add properties to a map");
            }
        }

        @Override
        public void renameKey(String oldKeyName, String newKeyName, Configuration configuration) {
            Object target = configuration.jsonProvider().getArrayIndex(parent, index);

View on GitHub (pinned to 62a4c9f0f6)

Solutions

  1. Verify the target element is a JSON array (jsonProvider().isArray / target instanceof List) before calling add().
  2. If the target is an object, use put(key, value) instead of add(value).
  3. Check the path itself: an index-based PathRef is the wrong ref type if the element is a map; adjust the path or use a property-based ref.
  4. Wrap the mutation in try/catch for InvalidModificationException to handle divergent documents gracefully.

Example fix

// before
context.add("$.items[0]", newItem); // throws if items[0] is an object
// after
Object target = context.read("$.items[0]");
if (target instanceof List) {
    context.add("$.items[0]", newItem);
} else {
    context.put("$.items[0]", "item", newItem);
}
Defensive patterns

Strategy: type-guard

Validate before calling

Object el = context.read("$.items[0]");
if (!(el instanceof List)) throw new IllegalStateException("$.items[0] is not an array");
context.add("$.items[0]", value);

Type guard

private static boolean isArray(Object o) { return o instanceof List; }

Try / catch

try { context.add(path, value); } catch (InvalidModificationException e) { log.warn("add() target at {} is not an array", path); }

Prevention

When it happens

Trigger: Calling JsonPath.parse(...).add(path, value) (or PathRef.add via a mutation template) where the path's INDEX-based variant resolves to a non-array element — e.g. the element at the given array index is an object `{}` or a string, not a `[...]`.

Common situations: Document shape differs from expectations: developer assumes `$.items[0]` is an array but the API returns an object at that position; using `.add()` on a path that actually points at a map when `put()` was intended; schema drift after an upstream API version change.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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