Skip to content

document-converter: renderDocx emits unopenable DOCX — template cover sectPr keeps un-remapped header/footer rIds (dangling rId15) #506

Description

@Madmat8

Summary

renderDocx (document-converter, engine pi-doc-engine:0.1.0) produces a DOCX that neither Word nor LibreOffice can open when the template contains a cover-page section. The generated word/document.xml keeps the template's original header/footer relationship IDs in the first <w:sectPr>, while word/_rels/document.xml.rels is rewritten with a shifted (off-by-one) numbering — leaving a dangling rId15.

LibreOffice fails with the unhelpful Error: source file could not be loaded; the file passes unzip -t and every part is well-formed XML, so the corruption is not obvious.

Repro

const dc = createDocumentConverter({ image: "pi-doc-engine:0.1.0", stagingDir: "/tmp/kb-staging" });
await dc.renderDocx("/abs/doc.md", {
  output: "/abs/doc.docx",
  template: "default",
  templatesDir: "/abs/docs/templates",   // template with enable_cover_page: true
});

Frontmatter: template: default, enable_cover_page: true, language: hu, toc.enabled: true.

Then: soffice --headless --convert-to pdf doc.docxError: source file could not be loaded.

Evidence from the produced package

word/_rels/document.xml.rels (rewritten by the engine):

rId target
rId9 header2.xml
rId10 header1.xml
rId11 header3.xml
rId12 footer2.xml
rId13 footer1.xml
rId14 footer3.xml

word/document.xmlsectPr #0 (the template's cover section, left untouched):

<w:sectPr ...>
  <w:headerReference w:type="even"    r:id="rId10"/>
  <w:headerReference w:type="default" r:id="rId11"/>
  <w:footerReference w:type="even"    r:id="rId12"/>
  <w:footerReference w:type="default" r:id="rId13"/>
  <w:headerReference w:type="first"   r:id="rId14"/>
  <w:footerReference w:type="first"   r:id="rId15"/>  <!-- DANGLING: no rId15 in rels -->

sectPr #1 (engine-generated, correct — consistent with the rels table):

<w:headerReference r:id="rId10" w:type="even"/>
<w:headerReference r:id="rId9"  w:type="default"/>
<w:footerReference r:id="rId13" w:type="even"/>
<w:footerReference r:id="rId12" w:type="default"/>
<w:headerReference r:id="rId11" w:type="first"/>
<w:footerReference r:id="rId14" w:type="first"/>

So sectPr #0 references rId10..rId15 (the template's original ids) while the rels were renumbered to rId9..rId14 — shifted by one, and the semantics are wrong too (headerReference type="first"rId14 = footer3).

Bisect that isolated it

Replacing the body with a single <w:p> while keeping the same package → loads fine. Adding only sectPr #0 back → fails. Rewriting sectPr #0's six refs to the same ids as sectPr #1 → DOCX opens and converts to PDF correctly.

Expected

Every r:id in all <w:sectPr> elements copied from the template must be remapped to the ids actually written into word/_rels/document.xml.rels. Ideally the engine should also validate that no r:id in document.xml is dangling before writing the output (fail loudly, not silently produce an unopenable file).

Environment

  • @blackbelt-technology/pi-dashboard-document-converter 0.7.0, engine image pi-doc-engine:0.1.0
  • dashboard develop @ 37d63b0
  • macOS arm64, LibreOffice 25.x (host) and the containerized LibreOffice — both refuse the file

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions