{"record":{"id":"bc454cb8fdc2d127","repo":"rust-lang/rust","slug":"non-absolute-xpath-is-not-supported-due-to-impleme","errorCode":null,"errorMessage":"Non-absolute XPath is not supported due to implementation issues","messagePattern":"Non-absolute XPath is not supported due to implementation issues","errorType":"exception","errorClass":"InvalidCheck","httpStatus":null,"severity":"error","filePath":"src/etc/htmldocck.py","lineNumber":223,"sourceCode":"def flatten(node):\n    acc = []\n    _flatten(node, acc)\n    return \"\".join(acc)\n\n\ndef make_xml(text):\n    xml = ET.XML(\"<xml>%s</xml>\" % text)\n    return xml\n\n\ndef normalize_xpath(path):\n    path = path.replace(\"{{channel}}\", channel)\n    if path.startswith(\"//\"):\n        return \".\" + path  # avoid warnings\n    elif path.startswith(\".//\"):\n        return path\n    else:\n        raise InvalidCheck(\n            \"Non-absolute XPath is not supported due to implementation issues\"\n        )\n\n\nclass CachedFiles(object):\n    def __init__(self, root):\n        self.root = root\n        self.files = {}\n        self.trees = {}\n        self.last_path = None\n\n    def resolve_path(self, path):\n        if path != \"-\":\n            path = os.path.normpath(path)\n            self.last_path = path\n            return path\n        elif self.last_path is None:\n            raise InvalidCheck(\"Tried to use the previous path in the first command\")","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/rust-lang/rust/blob/7088e4b63a9516ebfbfe2ab2d999cf01a528ac14/src/etc/htmldocck.py#L205-L241","documentation":"Raised as InvalidCheck by normalize_xpath() when an XPath passed to a directive does not start with '//' or './/'. The htmldocck XPath matching is built on ElementTree.findall, which requires absolute (descendant-or-self) paths because there is no concept of a 'current node' relative path implemented. Relative or single-slash paths are rejected up front.","triggerScenarios":"Any directive that resolves an XPath (has/matches/count/snapshot with 3 args, etc.) passes the path through normalize_xpath; if the path is like '/html/body' or 'div' (no leading //), InvalidCheck is raised at htmldocck.py:223.","commonSituations":"Authoring a rustdoc test directive with a CSS-like or absolute-single-slash selector instead of the required '//' descendant axis; converting a CSS selector to XPath incorrectly.","solutions":["Prefix the XPath with '//' to select descendants of the document root (e.g. `//div[@class='foo']`).","If you need a path relative to a previously matched node, use './/' (also accepted).","Avoid single leading '/' and bare tag names; they are not supported by this implementation."],"exampleFix":"// before\n//@ has: /html/body/div[@id='main'] 'text'\n\n// after\n//@ has: //body//div[@id='main'] 'text'","handlingStrategy":"validation","validationCode":"def xpath_is_supported(path: str) -> bool:\n    return path.startswith(\"//\") or path.startswith(\".//\")\n\nif not xpath_is_supported(xpath_from_directive):\n    raise SystemExit(\n        f\"htmldocck only supports '//' or './/' XPaths; got {xpath_from_directive!r}.\"\n    )","typeGuard":"def is_supported_xpath(path: str) -> bool:\n    return path.startswith(\"//\") or path.startswith(\".//\")","tryCatchPattern":"from srcetc_htmldocck import InvalidCheck\ntry:\n    norm = normalize_xpath(path)\nexcept InvalidCheck as e:\n    if \"Non-absolute XPath\" in str(e):\n        logging.error(\"rewrite the directive to use '//%s'\", path.lstrip('/.'))\n    raise","preventionTips":["Always begin XPaths in directives with '//'.","Convert CSS selectors to XPath carefully (CSS has no descendant-axis shorthand collision).","Add a lint rule that rejects directive XPaths not matching `^(\\.?)//`."],"tags":["htmldocck","rustdoc","xpath","test-template"],"backgroundTag":null,"analyzedSha":"7088e4b63a9516ebfbfe2ab2d999cf01a528ac14","analyzedAt":"2026-08-10T14:17:03.603Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}