json-path/JsonPath · error · InvalidModificationException

Can only rename properties in a map

Error message

Can only rename properties in a map

What it means

renameInMap only operates on JSON objects (maps). If the resolved target is an array or a scalar, renaming a property is meaningless, so it throws InvalidModificationException with 'Can only rename properties in a map'. The library refuses to perform a structurally impossible modification.

Source

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

    public abstract void convert(MapFunction mapFunction, Configuration configuration);

    public abstract void delete(Configuration configuration);

    public abstract void add(Object newVal, Configuration configuration);

    public abstract void put(String key, Object newVal, Configuration configuration);

    public abstract void renameKey(String oldKey,String newKeyName, Configuration configuration);

    protected void renameInMap(Object targetMap, String oldKeyName, String newKeyName, Configuration configuration){
        if(configuration.jsonProvider().isMap(targetMap)){
            if(configuration.jsonProvider().getMapValue(targetMap, oldKeyName) == JsonProvider.UNDEFINED){
                throw new PathNotFoundException("No results for Key "+oldKeyName+" found in map!");
            }
            configuration.jsonProvider().setProperty(targetMap, newKeyName, configuration.jsonProvider().getMapValue(targetMap, oldKeyName));
            configuration.jsonProvider().removeProperty(targetMap, oldKeyName);
        } else {
            throw new InvalidModificationException("Can only rename properties in a map");
        }
    }

    protected boolean targetInvalid(Object target){
        return target == JsonProvider.UNDEFINED || target == null;
    }

    @Override
    public int compareTo(PathRef o) {
        return this.getAccessor().toString().compareTo(o.getAccessor().toString()) * -1;
    }

    public static PathRef create(Object obj, String property){
        return new ObjectPropertyPathRef(obj, property);
    }

    public static PathRef create(Object obj, Collection<String> properties){
        return new ObjectMultiPropertyPathRef(obj, properties);

View on GitHub (pinned to 62a4c9f0f6)

Solutions

  1. Check that the resolved value is a map (configuration.jsonProvider().isMap(...)) before renaming.
  2. Adjust the path to point at the containing object, not at the array or scalar.
  3. If the target is an array, iterate its elements and rename the key within each object element individually.
  4. Validate the document structure against the expected schema before mutating it.

Example fix

// before
jsonPath.renameKey(doc, "$.items[0]", "old", "new", conf); // items[0] is an array index
// after
for (int i = 0; i < items.length; i++) {
    jsonPath.renameKey(doc, "$.items[" + i + "].obj", "old", "new", conf);
}
Defensive patterns

Strategy: type-guard

Validate before calling

Object target = JsonPath.read(document, path);
if (!(target instanceof Map)) {
    throw new IllegalArgumentException("Path '" + path + "' must resolve to an object for renameKey, got: "
        + (target == null ? "null" : target.getClass().getSimpleName()));
}

Type guard

boolean resolvesToMap(Object doc, String path, Configuration conf) {
    try {
        Object t = new JsonPath(path).read(doc, conf);
        return conf.jsonProvider().isMap(t);
    } catch (PathNotFoundException e) { return false; }
}

Try / catch

try {
    JsonPath.renameKey(document, path, oldKey, newKey, conf);
} catch (InvalidModificationException e) {
    throw new IllegalStateException("Path '" + path + "' does not resolve to a JSON object", e);
}

Prevention

When it happens

Trigger: Calling JsonPath.renameKey with a path that resolves to an array element or a primitive value instead of an object, e.g. renaming a key at "$.items[0]" when that element is a string.

Common situations: Assuming a path points to an object while the document shape changed; targeting an array index where the desired key lives one level deeper inside each element; JSON APIs returning scalars where objects were expected.

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/78d9ad2cab0ca05d. Report an issue: GitHub.