{"record":{"id":"549bb86e00655d91","repo":"gchq/CyberChef","slug":"invalid-xpath-details-n-err-message","errorCode":null,"errorMessage":"Invalid XPath. Details:\\n${err.message}.","messagePattern":"Invalid XPath\\. Details:\\\\n(.+?)\\.","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/XPathExpression.mjs","lineNumber":68,"sourceCode":"\n        let doc;\n        try {\n            doc = new xmldom.DOMParser({\n                errorHandler: {\n                    fatalError(e) {\n                        throw e;\n                    }\n                }\n            }).parseFromString(input, \"application/xml\");\n        } catch (err) {\n            throw new OperationError(\"Invalid input XML.\");\n        }\n\n        let nodes;\n        try {\n            nodes = xpath.parse(query).select({ node: doc, allowAnyNamespaceForNoPrefix: true });\n        } catch (err) {\n            throw new OperationError(`Invalid XPath. Details:\\n${err.message}.`);\n        }\n\n        const nodeToString = function(node) {\n            return node.toString();\n        };\n\n        return nodes.map(nodeToString).join(delimiter);\n    }\n\n}\n\nexport default XPathExpression;\n","sourceCodeStart":50,"sourceCodeEnd":81,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/XPathExpression.mjs#L50-L81","documentation":"Thrown by XPathExpression.run when xpath.parse(query).select(...) raises an exception while evaluating the user-supplied XPath expression against the already-parsed document. Unlike the XML error, this message is a template that includes err.message, so the actual parser reason (syntax error, unknown function, bad axis) is surfaced to the user.","triggerScenarios":"args[0] (the XPath query) is syntactically invalid or uses constructs the xpath library does not support — unbalanced brackets, undefined functions, namespace prefixes without bindings (though allowAnyNamespaceForNoPrefix is enabled), or invalid predicates.","commonSituations":"Typing an XPath by hand in the query field; copying an XPath 2.0/3.0 expression (e.g. using xs:string, for-expressions) that the 1.0 engine rejects; quoting issues when the query is embedded in a recipe JSON.","solutions":["Read err.message in the thrown OperationError — it states the exact parser complaint; fix that syntax (unbalanced quotes, predicates, axes).","Validate the query with a standalone XPath 1.0 tester against the same document.","Prefer XPath 1.0 constructs; replace XPath 2.0+ features (types, sequences, xquery-style) with 1.0 equivalents.","Ensure predicate brackets and string quotes are balanced and properly escaped in the recipe JSON."],"exampleFix":"// before\nchef.bake(xml, [{op:\"XPath Expression\", args:[\"//item[name='Widget\",\"\\n\"]}]); // unbalanced quote\n// after\nchef.bake(xml, [{op:\"XPath Expression\", args:[\"//item[name='Widget']\",\"\\n\"]}]);","handlingStrategy":"try-catch","validationCode":"// Validate XPath syntax against a tiny sample doc before baking\nfunction validXPath(q) { try { require(\"xpath\").parse(q).select({node: sampleDoc}); return true; } catch { return false; } }","typeGuard":"const isBalancedXPath = (q) => { const o=(q.match(/\\[/g)||[]).length, c=(q.match(/\\]/g)||[]).length; return o===c; };","tryCatchPattern":"try { result = chef.bake(input, recipe); } catch (e) { if (/Invalid XPath/.test(e.message)) { console.error(e.message); /* show err.message detail, fix query */ } else throw e; }","preventionTips":["Test XPath in a 1.0 engine before embedding in a recipe.","Avoid XPath 2.0+ features.","Balance and escape quotes in JSON-embedded queries."],"tags":["xpath","query-syntax","parse-error"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}