Why SuperDoc Shows Only the Last Image: A DOCX Internals Investigation

Published: (March 2, 2026 at 11:20 AM EST)
5 min read
Source: Dev.to

Source: Dev.to

The Symptom

The generated report contained multiple property images arranged in a grid.

Expected inside editorActual result inside SuperDoc
Image 1 → slot 1Slot 1 → last image
Image 2 → slot 2Slot 2 → last image
Image 3 → slot 3Slot 3 → last image

Strangely:

  • Microsoft Word → correct
  • LibreOffice → correct
  • Google Docs → correct
  • SuperDoc editor → wrong

So the DOCX itself was valid; the issue appeared editor‑specific.


Environment

ToolVersion
SuperDoc1.16.x
docx-templates4.15.0
Node20.x

Images were inserted using docx-templates loops and loaded into the editor via docxUrl.


First Check: Is the DOCX Corrupt?

Initial assumption: the DOCX generation might be broken.

Verification steps

  1. Opened in Word – ✅
  2. Opened in LibreOffice – ✅
  3. Converted to PDF – ✅
  4. Uploaded to Google Docs – ✅

Everything rendered correctly everywhere except inside the editor.
Conclusion: basic DOCX corruption ruled out.


Deep‑Debugging Approach

Since DOCX files are just ZIP archives, I extracted and inspected the raw XML:

word/document.xml
word/_rels/document.xml.rels
word/media/

The goal was to see how images were referenced internally.

Finding 1: Non‑Standard Relationship IDs

Normally DOCX uses relationship IDs like rId1, rId2, rId3.
The generated DOCX contained hash‑based IDs such as:

Test performed – converted all relationship IDs to standard rId1, rId2, … and updated references.

Result: No change in editor behaviour; all image slots still showed the last image.
Conclusion: relationship IDs were not the main cause.

Finding 2: Media Filenames

Generated filenames looked like:

template_document.xml_img2073076884.jpg

instead of the usual image1.jpg, image2.jpg.

Test performed – renamed them to a standard format and updated references.

Result: Still broken in the editor.

Conclusion: filename convention was not the cause.

Finding 3: Images Inside Tables?

Suspected that images inside table cells were being flattened or merged.

Check: raw XML structure – images were already in standalone paragraphs, not nested inside complex table drawing structures.

Result: No structural issue found.

Finding 4: Base64 External References

Converted images to base64‑encoded external references to rule out any media‑file‑resolution issue inside the editor.

Result: Still broken – all slots continued showing the last image.

Conclusion: The problem had to be in how the editor was interpreting drawing‑node identity, not how images were stored or referenced.


The Strongest Lead So Far (Unverified)

While inspecting the drawing XML for each image, a pattern emerged:

Every image had id="0".

According to the OOXML spec, this attribute must be unique per drawing object within a document.
docx-templates appears to assign id="0" to all generated images.

Working theory: SuperDoc uses ProseMirror (or a similar engine) for rendering. If the parser relies on pic:cNvPr/@id to distinguish drawing nodes, duplicate IDs could cause it to treat all images as the same node, with the last image loaded “winning” every slot.

Note: This is a hypothesis, not a confirmed fix. The next step is to patch docx-templates output to inject unique sequential IDs, perform a clean server restart, and verify the result. A failed test earlier turned out to be against old compiled code because the server hadn’t been restarted after a rebuild.


What Has Been Tried So Far

AttemptResult
Extract images from tableNo change
Rename relationship IDs to rId1/rId2No change
Rename media filenames to image1.jpgNo change
Convert images to base64 external refsNo change
Inspect drawing XMLFound duplicate id="0" across all images
Patch to unique IDsNot fully verified yet

Current Status

Issue is still under investigation.

Leading hypothesis: duplicate pic:cNvPr/@id="0" across all images causes the editor to collapse them into a single node.

Next steps

  1. Inject unique IDs into the drawing XML.
  2. Perform a full server restart.
  3. Run a clean verification (open the DOCX in SuperDoc, Word, LibreOffice, Google Docs).

Lessons From This Debugging Session

  1. If it works in Word, it can still be wrong
    Word tolerates many OOXML violations silently. Editors and converters are stricter. Never assume Word rendering equals correctness.

  2. Always inspect DOCX internally
    Treat a DOCX as a ZIP file. Unzip it, inspect the XML, search for patterns, verify structure – debugging becomes much faster.

  3. Rendering engines behave differently

ToolStrictness
WordVery forgiving
Google DocsModerate
LibreOfficeStrict
Editor enginesVery strict

Editor‑specific bugs often stem from structural assumptions the spec makes but Word quietly ignores.


Why I’m Documenting This

The bug is still unresolved, but the debugging process uncovered a plausible root cause (duplicate pic:cNvPr/@id). Sharing the journey may help others facing similar editor‑specific rendering quirks, and it serves as a reminder to validate DOCX output beyond “it looks fine in Word”.

If you’ve encountered similar behaviour with DOCX image rendering, I’d genuinely like to hear what you found.

0 views
Back to Blog

Related posts

Read more »