karatelabs/karate · error · RuntimeException
cannot set xpath on non-XML variable:
Error message
cannot set xpath on non-XML variable:
What it means
When karate.set() is given an XPath-style path (a third path argument), the target variable must be XML — a Node/Document or an XML string that can be converted to a Document. Karate throws this with the variable name appended when the target is any other type (JSON object, string that is not XML, number, etc.), since XPath cannot operate on it.
Solutions
- Use JSON-path style with JSON: karate.set('myVar', '$.child', value).
- Ensure the target variable contains XML (Document or XML string) before the XPath set.
- Convert data first, e.g. assign an XML response to the variable, then do the XPath set.
- Verify the variable name — the message names the offending variable.
Example fix
// before
karate.set('jsonVar', '/root/name', 'Bob');
// after
karate.set('jsonVar', '$.name', 'Bob'); Defensive patterns
Strategy: validation
Validate before calling
// before an XPath set, confirm the target is XML
if (typeof karate.get('xmlVar') === 'string' && karate.get('xmlVar').trim().charAt(0) !== '<') throw new Error('xmlVar is not XML'); Type guard
function isXmlLike(v) { return v != null && (typeof Node !== 'undefined' && v instanceof Node || (typeof v === 'string' && v.trim().charAt(0) === '<')); } Try / catch
try { karate.set(name, '/root/child', value); }
catch (e) { if ((e.message || '').indexOf('cannot set xpath on non-XML variable') >= 0) karate.set(name, '$.child', value); else throw e; } Prevention
- Match path syntax to data type: JSON-path ($.) for JSON, XPath (/) for XML.
- Assert the variable holds XML (response is xml) before XPath sets.
- Avoid reassigning XML variables to JSON mid-scenario.
- The error names the offending variable — check its last assignment.
When it happens
Trigger: karate.set('myVar', '/root/child', value) where myVar holds JSON or a non-XML string; using XPath syntax on a JSON variable by mistake.
Common situations: Mixing up JSON-path and XPath set syntax; a variable that was expected to hold XML but was reassigned to JSON earlier in the scenario; response parsed as JSON instead of XML.
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
- prettyXml() argument must be XML node or string
- xmlPath() needs two arguments: xml and path
- xmlPath() first argument must be XML node or string, but was
- xmlPath failed for path
- no results for xpath
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/7e8314f274c60f07.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/core/KarateJs.java:616
// Check if this is XPath (path starts with /) or target is XML
if (path.startsWith("/") || target instanceof Node) {
// XPath set on XML
Document doc;
if (target instanceof Document) {
doc = (Document) target;
} else if (target instanceof Node) {
doc = ((Node) target).getOwnerDocument();
} else if (target == null) {
// Create new XML document
doc = Xml.newDocument();
engine.put(name, doc);
} else if (target instanceof String && StringUtils.isXml((String) target)) {
// Convert XML string to Document
doc = Xml.toXmlDoc((String) target);
engine.put(name, doc);
} else {
throw new RuntimeException("cannot set xpath on non-XML variable: " + name);
}
if (value instanceof Node) {
Xml.setByPath(doc, path, (Node) value);
} else {
Xml.setByPath(doc, path, value == null ? "" : value.toString());
}
} else {
// Route through Json (Jayway) for full JSONPath semantics:
// dotted paths, [N] indices, $.foo[] array append, and
// ['hy-phen'] bracket-quoted keys. Mirrors
// the `set var.path = value` Gherkin step.
if (target == null) {
target = new java.util.LinkedHashMap<>();
engine.put(name, target);
}
Json.of(target).set(path, value);
}
}View on GitHub (pinned to a22eb90246)