The Exact Error
XPathException: expression expected
XPathResult Error: Invalid XPath expression
Error: Failed to execute 'evaluate' on 'Document': The string '//div[@class=active]' is not a valid XPath expression.
Or in Java:
javax.xml.xpath.XPathExpressionException: Invalid XPath expression
Quick summary: The XPath engine found a token it could not parse ā missing quotes around an attribute value, unclosed predicates, or an invalid axis name.
Why This Error Happens
XPath is strict about syntax. Common causes:
1. Missing quotes around attribute value ā [@class=active] instead of [@class='active']
2. Unclosed predicate bracket ā //div[@id='main' missing the closing ]
3. Invalid axis name ā //div/child:span instead of //div/child::span
4. Using CSS selector syntax in XPath ā .class-name or #id are CSS, not XPath
5. Malformed XML ā unclosed tags cause the document parse to fail before XPath runs
Step-by-Step Diagnosis
Step 1 ā Validate the XML first
const parser = new DOMParser();
const doc = parser.parseFromString(xmlString, 'application/xml');
const error = doc.querySelector('parsererror');
if (error) {
console.error('XML parse error:', error.textContent);
}
Step 2 ā Check the XPath expression for missing quotes
// WRONG ā attribute value without quotes
const bad = "//div[@class=active]";
// RIGHT
const good = "//div[@class='active']";
Step 3 ā Try the expression in isolation
try {
const result = doc.evaluate(
xpathExpr,
doc,
null,
XPathResult.ANY_TYPE,
null
);
} catch (e) {
console.error('XPath error:', e.message);
}
Solutions
Solution 1 ā Add quotes around attribute values
// WRONG:
//input[@type=text]
// RIGHT:
//input[@type='text']
//input[@type="text"]
Solution 2 ā Fix unclosed brackets
// WRONG:
//ul[@id='nav']/li[contains(@class,'active'
// RIGHT:
//ul[@id='nav']/li[contains(@class,'active')]
Solution 3 ā Use correct axis syntax
// WRONG (CSS-style):
div.container > span
// RIGHT (XPath):
//div[@class='container']/span
Solution 4 ā Wrap XPath evaluation in try-catch
function safeXPath(doc, expression) {
try {
return doc.evaluate(
expression,
doc,
null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null
);
} catch (e) {
console.error(`Invalid XPath "${expression}":`, e.message);
return null;
}
}
Real-World Examples
Scraping with Node.js + xpath package:
// WRONG:
const nodes = xpath.select('//a[@href=https://example.com]', doc);
// RIGHT:
const nodes = xpath.select('//a[@href="https://example.com"]', doc);
Java XPath:
XPathFactory xpathFactory = XPathFactory.newInstance();
XPath xpath = xpathFactory.newXPath();
XPathExpression expr = xpath.compile("//item[price > 10]");
NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
Quick Reference ā XPath Syntax Cheat Sheet
| Construct | Correct Syntax | Wrong Syntax |
|---|---|---|
| Attribute value | [@attr='value'] | [@attr=value] |
| Contains function | contains(@class,'name') | contains(@class, name) |
| Child axis | child::span | child:span |
| Position | //li[1] | //li[0] (XPath is 1-indexed) |
| And/or | and / or | && / ` |
Prevent This Error in the Future
1. Always quote string values in predicates: [@attr='value'].
2. Use an XPath tester to validate before embedding in code.
3. Validate XML separately ā fix parse errors before debugging XPath.
Use ToolNinja to Debug Faster
The XPath Tester lets you paste XML and test expressions interactively ā it highlights matching nodes and shows the exact error position.