{"record":{"id":"13c3105c4aea45d1","repo":"json-path/JsonPath","slug":"add-can-not-be-performed-to-multiple-properties","errorCode":null,"errorMessage":"Add can not be performed to multiple properties","messagePattern":"Add can not be performed to multiple properties","errorType":"exception","errorClass":"InvalidModificationException","httpStatus":null,"severity":"error","filePath":"json-path/src/main/java/com/jayway/jsonpath/internal/PathRef.java","lineNumber":315,"sourceCode":"        }\n        public void convert(MapFunction mapFunction, Configuration configuration) {\n            for (String property : properties) {\n                Object currentValue = configuration.jsonProvider().getMapValue(parent, property);\n                if (currentValue != JsonProvider.UNDEFINED) {\n                    configuration.jsonProvider().setProperty(parent, property, mapFunction.map(currentValue, configuration));\n                }\n            }\n        }\n\n        public void delete(Configuration configuration){\n            for (String property : properties) {\n                configuration.jsonProvider().removeProperty(parent, property);\n            }\n        }\n\n        @Override\n        public void add(Object newVal, Configuration configuration) {\n            throw new InvalidModificationException(\"Add can not be performed to multiple properties\");\n        }\n\n        @Override\n        public void put(String key, Object newVal, Configuration configuration) {\n            throw new InvalidModificationException(\"Put can not be performed to multiple properties\");\n        }\n\n        @Override\n        public void renameKey(String oldKeyName, String newKeyName, Configuration configuration) {\n            throw new InvalidModificationException(\"Rename can not be performed to multiple properties\");\n        }\n\n        @Override\n        public Object getAccessor() {\n            return Utils.join(\"&&\", properties);\n        }\n    }\n}","sourceCodeStart":297,"sourceCodeEnd":333,"githubUrl":"https://github.com/json-path/JsonPath/blob/62a4c9f0f65ba3f625aa0867d64c528ba72d09ec/json-path/src/main/java/com/jayway/jsonpath/internal/PathRef.java#L297-L333","documentation":"The multi-property PathRef variant represents a path that matched more than one property at once (e.g. a wildcard like `$..*` or `$.obj.*`). Jayway JsonPath deliberately refuses add()/put() on such refs because there is no single unambiguous destination for the new value, so it unconditionally throws InvalidModificationException(\"Add can not be performed to multiple properties\").","triggerScenarios":"Calling JsonPath.parse(...).add(path, value) where the path contains wildcards, deep-scan (`..`), filters, or otherwise evaluates to multiple properties — the resulting PathRef is the multi-property variant whose add() always throws.","commonSituations":"Using wildcard or filter paths in mutations (`$.*.tags`, `$..items`) assuming Jayway fans out the add to each match (it does not for add/put); upgrading code from read-only wildcard queries to mutations.","solutions":["Use a definite (non-wildcard) path that resolves to exactly one property before calling add().","Enumerate the matches yourself with read(path) returning a list/map, then add()/put() each concrete path in a loop (e.g. via pathsWithDef or map backwards API).","If the intent is fan-out mutation, consider MapFunction/transform with JsonActions instead of add().","Catch InvalidModificationException and fall back to per-match mutation."],"exampleFix":"// before\ncontext.add(\"$..items\", extraItem); // throws: matches multiple properties\n// after\nList<String> paths = context.read(\"$..items.path()\"); // or paths from listener\nfor (String p : paths) {\n    context.add(p, extraItem);\n}","handlingStrategy":"fallback","validationCode":"List<String> definitePaths = context.read(wildcardPath + \".path()\");\nif (definitePaths.size() != 1) throw new IllegalStateException(\"path must resolve to exactly one property for add()\");","typeGuard":null,"tryCatchPattern":"try { context.add(path, value); } catch (InvalidModificationException e) { // wildcard/multi-match: iterate concrete paths instead\n    for (String p : context.read(path + \".path()\")) { context.add(p, value); } }","preventionTips":["Never call add()/put() with wildcard, deep-scan, or filter paths.","Resolve matches first (path() / paths) and mutate each definite path in a loop.","Reserve mutation operations for definite paths only.","Document this constraint in team guidelines for JsonPath usage."],"tags":["json-path","mutation","wildcard-path"],"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"}