nexu-io/open-design · error · ValueError

slide relationship is missing for {rel_id or 'unknown id'}

Error message

slide relationship is missing for {rel_id or 'unknown id'}

What it means

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.

Source

Thrown at plugins/community/humanize-ppt/scripts/pptx_qa.py:86


def _resolve_target(source_part: str, target: str) -> str:
    if target.startswith("/"):
        return target.lstrip("/")
    return posixpath.normpath(posixpath.join(posixpath.dirname(source_part), target))


def _ordered_slide_parts(zf: zipfile.ZipFile) -> list[str]:
    presentation = "ppt/presentation.xml"
    root = _read_xml(zf, presentation)
    rels = _relationships(zf, presentation)
    parts: list[str] = []
    for slide_id in root.findall(".//p:sldIdLst/p:sldId", NS):
        rel_id = slide_id.attrib.get(f"{{{REL}}}id")
        rel = rels.get(rel_id or "", {})
        target = rel.get("Target")
        if not target:
            raise ValueError(f"slide relationship is missing for {rel_id or 'unknown id'}")
        resolved = _resolve_target(presentation, target)
        if resolved not in zf.namelist():
            raise ValueError(f"slide part is missing: {resolved}")
        parts.append(resolved)
    return parts


def _text(root: ET.Element) -> str:
    return " ".join(
        (node.text or "").strip()
        for node in root.findall(".//a:t", NS)
        if (node.text or "").strip()
    )


def _tokens(value: str) -> set[str]:
    return {
        token.lower()

View on GitHub (pinned to 5be4028344)

Solutions

  1. Re-open and re-save the deck in PowerPoint/Keynote (a 'round-trip') to regenerate consistent relationship parts, then retry pptx_qa.
  2. 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.
  3. Regenerate the deck from the source that produced it (the original tool/exporter) — corruption usually originates upstream.
  4. If the deck is essential and unrepairable, extract text from individual ppt/slides/slideN.xml files manually as a fallback.

Example fix

// before (corrupt rels part)
python3 pptx_qa.py inspect deck.pptx
# -> ValueError: slide relationship is missing for rId3

// after
# regenerate rels via PowerPoint round-trip, then:
unzip -p deck.pptx ppt/_rels/presentation.xml.rels | xmllint --format -
python3 pptx_qa.py inspect deck.pptx
Defensive patterns

Strategy: try-catch

Validate before calling

import zipfile

def presentation_rels_complete(path: str) -> bool:
    with zipfile.ZipFile(path) as zf:
        names = set(zf.namelist())
        if "ppt/presentation.xml" not in names:
            return False
        if "ppt/_rels/presentation.xml.rels" not in names:
            return False
        # parse sldId r:ids and confirm each has a Target in rels
        import xml.etree.ElementTree as ET
        root = ET.fromstring(zf.read("ppt/presentation.xml"))
        rels = ET.fromstring(zf.read("ppt/_rels/presentation.xml.rels"))
        ns = {"r": "http://schemas.openxmlformats.org/officeDocument/2006/relationships"}
        targets = {r.attrib["Id" ]: r.attrib.get("Target") for r in rels}
        for sld in root.findall(".//p:sldIdLst/p:sldId", {"p": "http://schemas.openxmlformats.org/presentationml/2006/main"}):
            rid = sld.attrib.get(f"{{{ns['r']}}}id")
            if not targets.get(rid):
                return False
    return True

Try / catch

try:
    parts = _ordered_slide_parts(zf)
except ValueError as exc:
    raise SystemExit(f"Deck structure is corrupt: {exc}. Re-save in PowerPoint and retry.") from exc

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/812d94f24210ca1e. Report an issue: GitHub.