Skip to content

Document with a dangling relationship fails to open with KeyError #64

Description

@toxicphreAK

A document that contains a relationship whose target part is not present in the package cannot be opened at all — the failure happens during package load, before any application code can inspect or skip the bad relationship.

Reproduction

Take the bundled default template, add one relationship pointing at a file that does not exist, and open it:

# word/_rels/document.xml.rels gains:
#   <Relationship Id="rIdBogus"
#     Type=".../image" Target="media/missing.png"/>
Document("broken.docx")
# KeyError: "There is no item named 'word/media/missing.png' in the archive"

A raw KeyError from zipfile escapes the OPC layer, so a caller cannot even distinguish this from a library bug without matching on the message.

Why it matters

This is one of the most reported failure modes upstream and it is not a synthetic case. Documents lose parts through incremental save, third-party generators, DRM/repair tools, and mail gateways that strip embedded media. Word itself opens these files without complaint — it treats a relationship with no target as absent.

Scope

  • Detect a relationship whose target part is missing while building the part graph in docx/opc/pkgreader.py, and drop it rather than raising
  • Emit a warning naming the rId and target so the loss is visible but non-fatal
  • Ensure the surviving Relationships collection stays consistent — rIds must not be dangling for later related_part() lookups
  • Decide and document the behaviour for a dropped image relationship reached via InlineShape — the shape element remains in the XML with an rId that no longer resolves
  • Round-trip test: open a package with a dangling rel, save it, confirm the result is loadable and the bad rel is gone
  • Unit tests covering internal and external relationship targets

Notes

Upstream has three open issues and two unmerged PRs on this, the oldest from 2019:

Related but distinct: python-openxml#1566 skips non-image parts when matching by sha1 in ImageParts, which is a second way a broken image relationship surfaces. Worth handling in the same pass.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions