{"record":{"id":"919acd924d497a3a","repo":"anthropics/skills","slug":"relationship-target-is-not-a-posix-part-name-tar-919acd","errorCode":null,"errorMessage":"relationship target is not a POSIX part name: {target!r}","messagePattern":"relationship target is not a POSIX part name: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"skills/xlsx/scripts/office/helpers/__init__.py","lineNumber":35,"sourceCode":"}\n\n_SCHEME_RE = re.compile(r\"^[A-Za-z][A-Za-z0-9+.\\-]*:\")\n\nSLIDE_REL_TYPE = \"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide\"\n\n\ndef opc_target(target: str, source_part: str, target_mode: str = \"\") -> str | None:\n    if not target:\n        return None\n    if target_mode.lower() == \"external\":\n        return None\n    if _SCHEME_RE.match(target):\n        return None\n\n    target = urllib.parse.unquote(target)\n\n    if \"\\\\\" in target:\n        raise ValueError(f\"relationship target is not a POSIX part name: {target!r}\")\n\n    if target.startswith(\"/\"):\n        joined = target.lstrip(\"/\")\n    else:\n        joined = posixpath.join(posixpath.dirname(source_part), target)\n\n    parts: list[str] = []\n    for segment in posixpath.normpath(joined).split(\"/\"):\n        if segment in (\"\", \".\"):\n            continue\n        if segment == \"..\":\n            if not parts:\n                raise ValueError(f\"relationship target escapes the package: {target!r}\")\n            parts.pop()\n        else:\n            parts.append(segment)\n\n    if not parts:","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/anthropics/skills/blob/f6656c1256d5a8adfa37db9110046ef20bac644c/skills/xlsx/scripts/office/helpers/__init__.py#L17-L53","documentation":"opc_target() normalizes an OOXML relationship target into a POSIX package part name. It rejects any target containing a backslash with this ValueError: OPC part names must use forward slashes, and a backslash usually means a producer wrote a Windows filesystem path into the .rels XML.","triggerScenarios":"Loading an xlsx/pptx/docx whose *.rels contains Target=\"folder\\file.xml\" or Target=\"..\\shared\\styles.xml\"; files round-tripped through tools that call Path() on targets and stringify back with os.sep on Windows; hand-authored or third-party-generated packages with backslash separators.","commonSituations":"Spreadsheets exported by niche ERP/Java/legacy tools; files manipulated on Windows by scripts that joined paths with backslashes before writing rels; otherwise valid documents that only Microsoft's lenient reader opens.","solutions":["Inspect the offending .rels: unzip the file and grep for 'Target=\"[^\"]*\\\\' to find the entry","Rewrite targets to forward slashes (folder/file.xml) — either in the source tool or with a small fix-up pass before loading","If you do not control the producer, pre-normalize a copy of the archive (replace \\\\ with / in *.rels) and load that"],"exampleFix":"# before (inside a .rels file)\n<Relationship Target=\"sheets\\\\sheet1.xml\" .../>\n# after\n<Relationship Target=\"sheets/sheet1.xml\" .../>","handlingStrategy":"validation","validationCode":"def rels_targets_are_posix(xlsx_path: str) -> bool:\n    import zipfile, re\n    with zipfile.ZipFile(xlsx_path) as zf:\n        for n in zf.namelist():\n            if n.endswith(\".rels\"):\n                data = zf.read(n).decode(\"utf-8\", \"replace\")\n                for m in re.finditer(r'Target=\"([^\"]*)\"', data):\n                    if \"\\\\\" in m.group(1):\n                        return False\n    return True","typeGuard":null,"tryCatchPattern":"try:\n    part = opc_target(target, source_part, mode)\nexcept ValueError as e:\n    if \"not a POSIX part name\" in str(e):\n        part = opc_target(target.replace(\"\\\\\", \"/\"), source_part, mode)  # only for trusted inputs\n    else:\n        raise","preventionTips":["Always build package paths with posixpath (never os.path/Path stringification) when writing .rels","Pre-scan third-party files for backslash targets before loading","Unit-test your writer with a filename containing spaces/unicode to catch separator bugs early"],"tags":["ooxml","rels","validation","path-separator"],"backgroundTag":null,"analyzedSha":"f6656c1256d5a8adfa37db9110046ef20bac644c","analyzedAt":"2026-08-14T16:09:17.493Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}