Technique

Pourquoi deux validateurs EN16931 divergent sur la même facture

Mis à jour le 6 min de lecture Par FacturX API

Trois validateurs, trois verdicts sur le même XML. Versions 1.3.x vs 1.4.0, warnings agrégés en « Invalide », calendrier FNFE du 30 juin 2026, et corpus public aligné ITB 16/16.

La même facture. Trois validateurs. Trois verdicts. Lequel croire ?

Ce n’est pas un bug rare. C’est le résultat mesurable de trois mécanismes qui se superposent : la version des artefacts Schematron, la façon dont l’outil agrège les warning en un feu global, et l’identifiant qu’il affiche pour une même règle. Les chiffres ci-dessous viennent d’une campagne du 17 août 2026 sur 16 documents publics (10 exemples CEN + 6 mutants). Chaque cellule a une recette rejouable.

En bref

  • Même octets, trois issues. Sur CII-SR-470-no-bt84.xml (SHA256 7877b5b6…362c33c9) : ITB et l’XSLT ConnectingEurope 1.3.16 échouent sur CII-SR-470 ; peppolvalidator.com répond valid ; Facturata et Mustang échouent sur BR-CO-27.
  • Un « Invalide » n’est pas forcément un fatal. SuperPDP affiche le headline Invalide sur CII_example1.xml alors que tous les findings listés sont flag="warning" — le même fichier est pass chez ITB, peppolvalidator (CII), Mustang et l’XSLT 1.3.16.
  • Les dates warning / fatal France ne sont pas dans les FAQ DGFiP. Elles sont dans la Note explicative FNFE-MPE V1.4.0 du 30 juin 2026 : version warning utilisable en réception jusqu’au 30 septembre 2026 ; version fatal applicable en réception à partir du 1er septembre et au plus tard le 1er octobre 2026.
  • Point de comparaison. Sur les 16 documents, ITB (release 1.3.16) et l’XSLT ConnectingEurope 1.3.16 donnent le même verdict et les mêmes ids — 16/16, zéro divergence. Neuf autres désaccords entre outils sont documentés, avec recettes.

Pour poser cette validation dans GitHub Actions : Valider vos factures EN16931 dans votre CI.

1. D’où viennent les divergences

Trois causes, mesurées. Pas une opinion sur un éditeur.

Versions d’artefacts différentes

ConnectingEurope publie EN16931 1.3.16 (10 avril 2026). La FNFE-MPE publie, avec les normes XP Z12-012/013/014 du 30 juin 2026, les schematrons 1.4.0 — y compris les règles additionnelles France (BR-FR-Flux2) en deux fichiers : version standard (flag="fatal") et version *_WARNING.sch.

Un outil encore en 1.3.x et un outil en 1.4.0 ne posent pas la même question. Un outil qui exécute le fichier warning et un outil qui exécute le fichier fatal ne posent pas la même question non plus, même à numéro de version égal.

Agrégation des warnings

Sur CII_example1.xml (SHA256 0c12e3ca9aab58299e6271b89d061274694c62159510ca2d848f13d287ee4f99) :

SurfaceVerdictIds
XSLT EN 1.3.16 / ITB / peppolvalidator / Mustangpassaucun failed-assert
SuperPDPheadline InvalidePEPPOL-EN16931-R008, BR-FR-05_*, BR-FR-08_BT-23, BR-FR-10_BT-30, BR-FR-12_BT-49, BR-FR-13_BT-34, BR-FR-16_* — tous flag="warning" ; aucun bloc Erreur
B2BrouterXSD « non »Schematron affiché 0 / 0

Le XML CEN n’a pas changé. Ce qui change, c’est le feu que l’interface allume au-dessus d’une liste de warnings, et les couches additionnelles (Peppol, BR-FR) que l’outil a choisi d’exécuter.

Même règle, autre identifiant — ou pas de règle du tout

Le mutant M6 CII-SR-470-no-bt84.xml (copie de CII_example3 sans BT-84, SHA256 7877b5b6b0e01a004bc9fd60cb6128d97453d80f31337bc6cb94f320362c33c9) :

SurfaceVerdictId verbatim
XSLT EN 1.3.16failCII-SR-470
ITB (validationType=cii, 17 août 2026 14:56 PT)failCII-SR-470 — « Either the IBAN or a Proprietary ID (BT-84) shall be used. »
peppolvalidator.comvalidni CII-SR-470 ni BR-CO-27
Facturata (check=base)failBR-CO-27
MustangfailBR-CO-27 (FX-SCH-A-000132)
SuperPDPInvalideCII-SR-470 en Erreur (1/1) + BR-FR en warning

BR-CO-27 n’apparaît pas dans l’artefact ConnectingEurope 1.3.16 (0 occurrence). C’est l’id d’une autre feuille (Factur-X / Mustang). peppolvalidator valid n’est pas un pass de l’XSLT officiel. Trois lectures, un seul fichier.

D’autres désaccords mesurés le même jour, sans adjectif :

  • Profil ZUGFeRD 1 comfort (urn:ferd:CrossIndustryDocument:invoice:1p0:comfort) : ITB passe le Schematron EN16931 ; Facturata s’arrête sur XSD « Wrong level ‘comfort’ » ; Mustang « Unsupported profile type … comfort » ; SuperPDP « Aucun validateur de trouvé pour ce format de fichier ». La règle mutante (BT-31, date, décimal) n’est alors jamais atteinte.
  • UBL CEN ubl-tc434-creditnote1.xml : ITB / Mustang / XSLT 1.3.16 passent ; peppolvalidator échoue sur PEPPOL-EN16931-R004 (il exécute BIS 3.0) ; Facturata refuse l’UBL (« UBL validation is not supported yet »).
  • Règles Factur-X hors EN16931 : XRechnung-O.xml et huf_example_cii.xml passent ITB / XSLT 1.3.16 ; Facturata et Mustang échouent sur BR-FX-EN-04.

Neuf fiches, chacune liée à une recette : voir le corpus public ci-dessous.

2. Le calendrier des sévérités (note FNFE-MPE V1.4.0, 30 juin 2026)

Les règles additionnelles France (BR-FR-Flux2, BR-FR-CDV) existent en deux régimes de sévérité. La bascule est datée. Source unique citée ici : Schematrons en application des Règles de gestion de la norme XP Z12-012, Version 1.4.0 du 30 juin 2026, chapitre APPLICATION, pages 5 et 10–11. Dépôt fnfempe/France_RFE, commit a63e6b538bdaff460f17c38dc1bc5455cf1ba35a (tag v1.4.0.03).

La note dit :

  • la version warning est utilisable en réception dès la publication jusqu’au 30 septembre 2026 (« pour rester en mode passant pour les premiers flux ») ;
  • la version standard (flag fatal) est applicable en réception à la place de la version warning à partir du 1er septembre et au plus tard le 1er octobre 2026 ;
  • en émission, la version warning est utilisable jusqu’au 31 août ; la version fatal doit être appliquée à partir du 1er septembre 2026.

Elle ne fixe pas le jour exact entre le 1er septembre et le 1er octobre pour la réception. Elle ne dit pas avoir force de décret, d’arrêté ou de BOI. Les corpus DGFiP ouverts le 17 août 2026 (guide pratique juillet 2026, FAQ, fiches, spécifications externes v3.2) ne contiennent pas les chaînes warning / fatal au sens des flags Schematron.

Conséquence pratique, sans dramatiser : un gabarit qui « passe avec warnings » sous un schematron 1.3.x ou sous le fichier *_WARNING.sch 1.4.0 peut être rejeté une fois que la plateforme exécute le fichier fatal. Le XML n’a pas bougé. La version exécutée, si.

Ce qu’un intégrateur peut faire maintenant :

  1. Valider ses gabarits contre les schematrons 1.4.0 en régime fatal, pas seulement contre la version que sa plateforme exécute aujourd’hui.
  2. Traiter un warning BR-FR actuel comme une correction à poser avant octobre.
  3. Automatiser le contrôle EN16931 cœur en CI — l’Action GitHub — pour que la bascule de sévérité ne dépende pas d’une relecture manuelle.

3. Comment on tranche

Quand deux outils se contredisent, le point de comparaison utile est un artefact nommé, versionné, rejouable — pas un feu de dashboard.

Validateur ITB de la CommissionPOST https://www.itb.ec.europa.eu/vitb/rest/invoice/api/validate, types cii / ubl / credit affichés « release 1.3.16 ». Campagne du 17 août 2026, 14:56–14:57 PT, 16 documents, 16 HTTP 200 : même polarité et mêmes ids que l’XSLT ConnectingEurope 1.3.16. Zéro divergence.

Corpus public facturxapi/en16931-oracles :

  • 10 exemples CEN, recettes SVRL, RESULTS.sha256 = dffb88780654fb4861df84bbd6df18aae5d89b0a5b8f4fd12ce5fb5f9a7f0dab ;
  • 10 mutants qui doivent échouer, ids documentés ;
  • replay CI public : run 32081271235 (success, 17 août 2026 23:38 UTC).

Les neuf désaccords entre outils commerciaux (ids, polarité, stop profil, agrégation warning) sont dans les recettes du 17 août 2026 — pas dans un tableau marketing. Ce corpus ne couvre pas le profil France / BR-FR : c’est écrit dans son README.

4. Ce que ça change pour l’intégrateur

Tester contre un validateur, c’est tester contre sa version d’artefacts, son agrégat warning/fatal, ses ids. Tester contre un corpus à verdicts signés, c’est figer la question : « ce fichier doit passer / ce fichier doit échouer sur cet id ».

En pratique :

  1. Garde-fou CI gratuitfacturxapi/validate-einvoice@v1 sur vos XML + les mutants en16931-oracles (un job doit échouer sur BR-CO-16). Détail : Valider dans GitHub Actions.
  2. Référence publique — le même XSLT 1.3.16 que l’ITB a rejoué 16/16 le 17 août 2026.
  3. Le reste de la chaîne — conteneur PDF/A-3, réparation de format, profil France, rapport partageable : documentation API. Ce n’est pas ce que l’Action prétend faire.

Si deux outils divergent encore après ça, la question utile n’est plus « lequel a raison en général ». C’est : quel artefact, quelle version, quel flag, quel id chaque outil a réellement exécuté.

Continuer la lecture

Étape suivante recommandée

Vous voulez figer un verdict EN16931 dans la CI, puis traiter le PDF et le profil France à part.

Voici ce que vous allez obtenir :

  • Coller l'Action validate-einvoice@v1
  • Ajouter un mutant BR-CO-16 qui doit rester rouge
  • Lire le catalogue BR-* pour le correctif
  • Ouvrir la doc pour PDF/A-3 et profil France
#EN16931 #validation #schematron #ITB #factur-x #BR-* #divergences