karatelabs/karate · error · RuntimeException
cannot replace root path $
Error message
cannot replace root path $
What it means
Json.setInternal() implements Json.set()/setAsString(); replacing the entire root ($, i.e. the whole document) is not supported because the document context was built around the existing root value. Callers must instead mutate paths inside the document.
Solutions
- Set child paths instead, e.g. set("$.field", value)
- Build a new Json from the desired value via Json.of(newMap) and use that object
- Use document mutation helpers or re-create the Json wrapper
Example fix
// before
json.set("$", newMap);
// after
json.set("$.field", newMap.get("field")); // or: json = Json.of(newMap); Defensive patterns
Strategy: validation
Validate before calling
if ("$".equals(path) || path == null) { throw new IllegalArgumentException("set() cannot replace root; use Json.of() to build a new document"); } Try / catch
try { json.set(path, value); } catch (RuntimeException e) { if ("cannot replace root path $".equals(e.getMessage())) { json = Json.of(value); } else { throw e; } } Prevention
- Never pass "$" or empty path to Json.set; set child paths
- Rebuild the document with Json.of(newMap) for wholesale replacement
- Wrap path writes in a helper that rejects root paths up front
When it happens
Trigger: json.set("$", newMap) or json.set("$", value), or setAsString("$", jsonText) — targeting the root path.
Common situations: Wanting to wholesale-replace a parsed document's content; porting code that assumed set('$') acts like assignment.
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
- input must not be null
- input string must not be empty or blank
- invalid json: input is null or blank
- invalid json: not a JSON object or array
- invalid json
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/28c2e9ad034e24be.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/common/Json.java:305
if (leftPos == -1) {
return -1;
}
int rightPos = s.indexOf(']', leftPos);
String num = s.substring(leftPos + 1, rightPos);
if (num.isEmpty()) {
return -1;
}
try {
return Integer.parseInt(num);
} catch (NumberFormatException e) {
return -1;
}
}
private void setInternal(String path, Object o) {
path = prefix(path);
if ("$".equals(path)) {
throw new RuntimeException("cannot replace root path $");
}
boolean forArray = isArrayPath(path);
if (!pathExists(path)) {
createPath(path, forArray);
}
Pair<String> pair = toParentAndLeaf(path);
if (forArray) {
int index = arrayIndex(pair.right);
if (index == -1) {
doc.add(arrayKey(path), o);
} else {
doc.set(path, o);
}
} else {
doc.put(pair.left, pair.right, o);
}
}
View on GitHub (pinned to a22eb90246)