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

  1. Use JSON-path style with JSON: karate.set('myVar', '$.child', value).
  2. Ensure the target variable contains XML (Document or XML string) before the XPath set.
  3. Convert data first, e.g. assign an XML response to the variable, then do the XPath set.
  4. 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

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


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)