Skip to content

Build1 publisher3 min readPublished

Two common Factur-X construction errors clear both veraPDF and Mustang

PDFik's write-up on shipping Factur-X output argues the container, not the XML attachment, is the hard part, and that a clean validator run says nothing about whether German or French rules accept the file.

The Engineer · Build desk

What happened

  • Factur-X and ZUGFeRD 2.x are one standard under two names: a PDF a person reads, carrying an embedded UN/CEFACT Cross Industry Invoice XML that follows the EN 16931 semantic model.
  • A valid hybrid file has four independently breakable layers, and the container alone needs an OutputIntent with an embedded sRGB ICC profile plus XMP declaring pdfaid:part=3 and pdfaid:conformance=B.
  • Germany's duty to receive e-invoices started on 1 January 2025, while the transition rule pushes the duty to issue out to 2027 for larger companies and 2028 for everyone else.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • cost The failure mode is silent, so the cost of a mis-built container lands after delivery, inside the recipient's accounting system, rather than in your validator run.
  • decision Profile choice is a legal decision, not just a build flag: the BMF accepts ZUGFeRD from 2.0.1 while excluding MINIMUM and BASIC-WL.
  • capability One of the five container requirements arrives free from the renderer, which leaves metadata and attachment plumbing as the work you actually have to write.

Chromium hands you a plain PDF [4]. PDF/A-3b on top of that wants an OutputIntent with an embedded sRGB ICC profile, XMP metadata carrying `pdfaid:part=3` and `pdfaid:conformance=B`, every font embedded, no JavaScript and no encryption [3]. Most of that is post-processing on a file you already have. Font embedding is the exception, because it is already done.

The dozen local test renders behind that finding come from Vitalii, founder of the hosted HTML-to-PDF service PDFik, which shipped Factur-X output this week and discloses it up front [9]. The renders covered Latin, Cyrillic, Greek, CJK, SVG text, form controls, a web font fetched from Google Fonts and a family that does not exist anywhere; in every case the text font landed in the output as a subsetted CIDFontType2 with its outlines in `/FontFile2`, and one line of text pulled a 1 MB, 4,651-glyph face down to a 47 KB subset [6]. That subset is about 4.6 percent of the original face [7]. PDF/A-3b also permits transparency, so CSS opacity is not the constraint it was under PDF/A-1 [5]. Rendering is the one part of this pipeline that just works.

The rest does not adjudicate itself. Four layers make a valid file and each can be wrong independently: the PDF/A-3 container, the attachment relationship, the metadata that has to declare a custom schema, and the CII payload [2]. The write-up promises a section on the traps that cost its author days, and states at the top that two of the most common mistakes pass both veraPDF and Mustang [24][8]. Read that as a claim about your acceptance test. If a construction error is invisible to both tools, a green run tells you the file is well-formed and nothing about whether it is the file the tax authority wants.

German rules make the gap concrete. The BMF names XRechnung and ZUGFeRD from version 2.0.1 as satisfying the VAT-law requirements, and explicitly excludes the MINIMUM and BASIC-WL profiles [14]. Profile selection happens in whatever writes your CII, which no path in the write-up generates for you [10], and no PDF/A checker has an opinion about it.

The calendar is the other thing to read before scoping the work. Germany has required businesses to be able to receive e-invoices since 1 January 2025, small firms included, even though they are exempt from issuing [11]. Issuing is where the transition rule bites: until 31 December 2026 any issuer may still send an ordinary invoice, meaning paper or an unstructured file such as a plain PDF, and until 31 December 2027 if the previous year's turnover was EUR 800,000 or less [12]. In practice, per the write-up, the duty to issue starts in 2027 for larger companies and 2028 for the rest [13], two to three years behind the duty to receive [21]. France runs earlier: from 1 September 2026 every covered business must be able to receive through an approved platform, large enterprises and mid-caps must also issue from that date, and SMEs and micro-enterprises follow on 1 September 2027 [15]. Approved platforms have to transmit CII, UBL or Factur-X [16]. That French date, 1 September 2026, is the first hard deadline a hybrid pipeline actually has to meet [22].

Two nearby jurisdictions will not take the file. Belgium has mandated B2B e-invoicing over Peppol since 1 January 2026, and the write-up cites the position that emailing a PDF is no longer enough, which leaves the hybrid as a courtesy copy [17]. Poland's KSeF accepts structured XML only, with FA(3) in force since 1 February 2026 [18], and an attachment there is a structured element inside the XML that requires notifying the tax office first, so the hybrid PDF has nothing to attach itself to [19]. The container work is scoped by geography: it earns its keep in Germany and France, and rides along as a readable extra elsewhere [20].

What to watch

  • Whether Germany's transition rule holds through 31 December 2026, since any extension moves the issuing duty again.
  • Whether the DGFiP's approved-platform format list stays at CII, UBL and Factur-X; dropping the hybrid would strand the container work.
  • Whether veraPDF or Mustang add checks for the construction errors that currently pass both.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories