{"record":{"id":"812d94f24210ca1e","repo":"nexu-io/open-design","slug":"slide-relationship-is-missing-for-rel-id-or-unkn","errorCode":null,"errorMessage":"slide relationship is missing for {rel_id or 'unknown id'}","messagePattern":"slide relationship is missing for (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"plugins/community/humanize-ppt/scripts/pptx_qa.py","lineNumber":86,"sourceCode":"\n\ndef _resolve_target(source_part: str, target: str) -> str:\n    if target.startswith(\"/\"):\n        return target.lstrip(\"/\")\n    return posixpath.normpath(posixpath.join(posixpath.dirname(source_part), target))\n\n\ndef _ordered_slide_parts(zf: zipfile.ZipFile) -> list[str]:\n    presentation = \"ppt/presentation.xml\"\n    root = _read_xml(zf, presentation)\n    rels = _relationships(zf, presentation)\n    parts: list[str] = []\n    for slide_id in root.findall(\".//p:sldIdLst/p:sldId\", NS):\n        rel_id = slide_id.attrib.get(f\"{{{REL}}}id\")\n        rel = rels.get(rel_id or \"\", {})\n        target = rel.get(\"Target\")\n        if not target:\n            raise ValueError(f\"slide relationship is missing for {rel_id or 'unknown id'}\")\n        resolved = _resolve_target(presentation, target)\n        if resolved not in zf.namelist():\n            raise ValueError(f\"slide part is missing: {resolved}\")\n        parts.append(resolved)\n    return parts\n\n\ndef _text(root: ET.Element) -> str:\n    return \" \".join(\n        (node.text or \"\").strip()\n        for node in root.findall(\".//a:t\", NS)\n        if (node.text or \"\").strip()\n    )\n\n\ndef _tokens(value: str) -> set[str]:\n    return {\n        token.lower()","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/plugins/community/humanize-ppt/scripts/pptx_qa.py#L68-L104","documentation":"Raised in _ordered_slide_parts (pptx_qa.py) when iterating slide IDs in ppt/presentation.xml: for each p:sldId it looks up the relationship by r:id; if the relationship has no Target (the rel entry is missing or malformed), it raises ValueError. This indicates a structurally corrupt .pptx package where presentation.xml references slides that the relationships part does not define.","triggerScenarios":"Running pptx_qa dump/inspect/checkup on a .pptx whose ppt/_rels/presentation.xml.rels is missing an entry for one of the sldId r:id values, or where the rel exists but has no Target attribute. Reproducible with hand-edited OOXML, partial exports from non-PowerPoint tools, or files truncated mid-write.","commonSituations":"A deck generated by a third-party converter (LibreOffice, Keynote export, python-pptx misused) that emits sldIdLst entries without matching relationships; a file corrupted in transit/storage; a deck recovered from a damaged zip where the rels part was dropped; merging decks incorrectly leaving dangling sldId references.","solutions":["Re-open and re-save the deck in PowerPoint/Keynote (a 'round-trip') to regenerate consistent relationship parts, then retry pptx_qa.","Inspect the package directly: `unzip -l deck.pptx` and `unzip -p deck.pptx ppt/_rels/presentation.xml.rels` to find which r:id is missing a Target.","Regenerate the deck from the source that produced it (the original tool/exporter) — corruption usually originates upstream.","If the deck is essential and unrepairable, extract text from individual ppt/slides/slideN.xml files manually as a fallback."],"exampleFix":"// before (corrupt rels part)\npython3 pptx_qa.py inspect deck.pptx\n# -> ValueError: slide relationship is missing for rId3\n\n// after\n# regenerate rels via PowerPoint round-trip, then:\nunzip -p deck.pptx ppt/_rels/presentation.xml.rels | xmllint --format -\npython3 pptx_qa.py inspect deck.pptx","handlingStrategy":"try-catch","validationCode":"import zipfile\n\ndef presentation_rels_complete(path: str) -> bool:\n    with zipfile.ZipFile(path) as zf:\n        names = set(zf.namelist())\n        if \"ppt/presentation.xml\" not in names:\n            return False\n        if \"ppt/_rels/presentation.xml.rels\" not in names:\n            return False\n        # parse sldId r:ids and confirm each has a Target in rels\n        import xml.etree.ElementTree as ET\n        root = ET.fromstring(zf.read(\"ppt/presentation.xml\"))\n        rels = ET.fromstring(zf.read(\"ppt/_rels/presentation.xml.rels\"))\n        ns = {\"r\": \"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"}\n        targets = {r.attrib[\"Id\" ]: r.attrib.get(\"Target\") for r in rels}\n        for sld in root.findall(\".//p:sldIdLst/p:sldId\", {\"p\": \"http://schemas.openxmlformats.org/presentationml/2006/main\"}):\n            rid = sld.attrib.get(f\"{{{ns['r']}}}id\")\n            if not targets.get(rid):\n                return False\n    return True","typeGuard":null,"tryCatchPattern":"try:\n    parts = _ordered_slide_parts(zf)\nexcept ValueError as exc:\n    raise SystemExit(f\"Deck structure is corrupt: {exc}. Re-save in PowerPoint and retry.\") from exc","preventionTips":["Validate the .pptx package structure before deep inspection (rels + parts present).","Treat decks from third-party converters with suspicion — round-trip through PowerPoint first.","Keep backups of decks before any in-place edit.","If ingesting user-supplied decks, catch ValueError and report 'corrupt file' to the user rather than crashing."],"tags":["powerpoint","ooxml","validation","file-corruption","pptx-qa"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}