Validierungsfehler bei KSeF FA(3): Fehlersuche für Entwickler

So trennen Sie bei KSeF FA(3) XML-, Semantik-, Duplikat-, Authentifizierungs- und Transportfehler und wiederholen Anfragen sicher.

Ernest Bursa

Ernest Bursa

Founder · · 13 Min. Lesezeit
A senior integration engineer tracing red, yellow, and blue network cables between devices in a blue-hour maker lab

Ein Fehler bei KSeF FA(3) ist keine einheitliche Fehlerart. Dahinter kann ein HTTP-Fehler, eine synchrone API-Ausnahme, ein asynchroner Rechnungsstatus, ein Sitzungsstatus oder ein Authentifizierungsstatus stecken. Für die Diagnose brauchen Sie drei Werte zusammen: den Vorgang, den Status-Namensraum und den Code. Beheben Sie anschließend deterministische Fehler, gleichen Sie Duplikate und nicht eindeutige Übermittlungen ab und wiederholen Sie nur tatsächlich vorübergehende Fehler.

Dieser Leitfaden bezieht sich auf die Spezifikation der produktiven KSeF-API 2.6.1, die am 28. August 2026 verfügbar war. TEST stellt bereits Version 2.7.1 bereit. Prüfen Sie daher die aktuelle OpenAPI-Spezifikation für die Produktivumgebung und die zur Laufzeit für Sie geltenden Limits, bevor Sie eine Tabelle als dauerhaft gültig behandeln. Dies ist ein technischer Leitfaden, keine Steuer- oder Rechtsberatung.

Was gilt bei KSeF FA(3) als Validierungsfehler?

Die Annahme durch KSeF ist eine Verarbeitungskette und nicht nur eine einzelne XSD-Prüfung. Eine Online-Rechnung kann alle folgenden Schritte durchlaufen:

  1. Ihr Client serialisiert die Geschäftsrechnung als FA(3)-XML.
  2. Er bildet den Hashwert der exakt zu sendenden Bytes und verschlüsselt sie.
  3. KSeF nimmt die API-Anfrage synchron an oder lehnt sie ab.
  4. Eine angenommene Anfrage geht in die asynchrone Rechnungsverarbeitung über.
  5. KSeF prüft Datei, Verschlüsselung, Berechtigungen, mögliche Duplikate und ausgewählte semantische Regeln.
  6. Eine erfolgreiche Rechnung erhält eine KSeF-Nummer und erfüllt damit die Voraussetzung für eine UPO.

Die erste wichtige Unterscheidung verläuft zwischen Transport- und Rechnungserfolg. POST /sessions/online/{referenceNumber}/invoices gibt HTTP 202 Accepted mit einer Rechnungsreferenz zurück. Das bedeutet lediglich, dass die Verarbeitung begonnen hat. Es bedeutet weder, dass das XML die Validierung bestanden hat, noch dass die Rechnung eine KSeF-Nummer oder eine UPO erhalten hat.

Speichern Sie die zurückgegebene Rechnungsreferenz, bevor Sie weitere Schritte ausführen. Fragen Sie danach das Rechnungsergebnis ab und behandeln Sie das Sitzungsergebnis als unabhängiges Signal. Die OpenAPI-Spezifikation für die Produktivumgebung zeigt sogar eine Sitzung mit Status 200, die zehn Rechnungen enthält: Acht waren erfolgreich, zwei sind fehlgeschlagen. Eine erfolgreiche Sitzung beweist nicht, dass jede darin enthaltene Rechnung erfolgreich war.

Der umgekehrte Fehler kommt ebenfalls häufig vor: HTTP 200 von einem Status-Endpunkt bedeutet, dass die Statusanfrage funktioniert hat, nicht dass die Rechnung erfolgreich war. Der Antwortkörper kann den Verarbeitungsstatus 440, 450 oder einen anderen Fehler enthalten.

Warum ist ein KSeF-Code ohne Kontext bedeutungslos?

Angenommen, in einem Protokolleintrag steht lediglich KSeF error 440. Sie wissen dann noch immer nicht, was passiert ist.

  • Rechnungsstatus 440 bedeutet, dass ein Rechnungsduplikat vorliegt.
  • Sitzungsstatus 440 bedeutet, dass die Sitzung abgebrochen wurde, etwa nach einer Zeitüberschreitung oder weil sie keine Rechnungen enthielt.
  • Rechnungsstatus 450 steht für einen semantischen Validierungsfehler.
  • Authentifizierungsstatus 450 steht für ein ungültiges Token.

Diese Werte gehören nicht zu einem globalen Verzeichnis von Fehlernummern, sondern zu Antwortmodellen. Ein brauchbarer Diagnoseeintrag muss deshalb den Kontext der Nummer enthalten.

Zu speicherndes Feld Warum es wichtig ist
Umgebung und API-Version TEST und Produktivumgebung können unterschiedliche Verträge verwenden
Vorgang oder Endpunkt Bestimmt, welcher Status-Namensraum gilt
HTTP-Status Trennt die Verarbeitung der Anfrage und des Transports vom Verarbeitungsergebnis
Ausnahme- oder Verarbeitungscode Ordnet den Fehler innerhalb dieses Namensraums ein
Beschreibung, details und extensions Enthält verwertbare Diagnosedaten des Servers und ursprüngliche Referenzen
Sitzungs- und Rechnungsreferenzen Ermöglicht es, Statusabfragen fortzusetzen und unklare Ergebnisse abzugleichen
Exakter XML-Hashwert und Größe Verknüpft eine Antwort mit den Bytes, die Sie übermitteln wollten

Vergeben Sie für diesen Datensatz eine interne Korrelations-ID und hängen Sie sie an jeden erneuten Versuch und jede Statusabfrage. So kann ein Dashboard Fehler gruppieren, ohne die Belege zu verwerfen, die Sie zum Reproduzieren eines Einzelfalls benötigen.

Halten Sie synchrone Anfrageausnahmen außerdem von asynchronen Rechnungsstatus getrennt. Beim Online-Versand gehören zu den aktuellen HTTP-400-Ausnahmen unter anderem ein ungültiger Sitzungszustand (21180), eine abweichende Größe (21402), ein abweichender Hashwert (21403) und eine ungültige Anfrage (21405). Wenn Sie X-Error-Format: problem-details anfordern, können unterstützte Anfragefehler strukturierte Problem Details verwenden. Keiner dieser Codes gehört in eine Tabelle mit Rechnungsstatus.

Welche Rechnungsstatus bedeuten Warten, Beheben, Abgleichen oder Wiederholen?

Verwenden Sie den Rechnungsstatus des Endpunkts für den Status einer einzelnen Rechnung und nicht den HTTP-Status der betreffenden GET-Anfrage.

Rechnungsstatus Bedeutung in Produktivversion 2.6.1 Standardmaßnahme
100, 150 Zur weiteren Verarbeitung angenommen / in Verarbeitung Warten und später mit wachsendem Intervall erneut abfragen
200 Erfolgreich verarbeitet KSeF-Nummer erfassen sowie UPO abrufen und speichern
405 Wegen eines Sitzungsfehlers abgebrochen Zuerst den Sitzungsfehler prüfen
410 Ungültiger Berechtigungsumfang Autorisierung korrigieren; XML nicht wahllos ändern
415 Rechnung mit Anhang kann nicht gesendet werden Berechtigung für Anhänge oder Rechnungsformular korrigieren
430 Prüfung der Rechnungsdatei fehlgeschlagen Bytes, XML, Schema, Limits, Hashwert und zugehörige Dateiregeln prüfen
435 Entschlüsselung fehlgeschlagen Schlüssel und Verschlüsselungsverarbeitung korrigieren
440 Rechnungsduplikat Mit der ursprünglichen Sitzung und KSeF-Nummer abgleichen
450 Semantische Validierung fehlgeschlagen Rechnungsdaten anhand der zurückgegebenen Details korrigieren
500 Unbekannter interner Status Diagnosedaten bewahren und vor einer begrenzten Wiederherstellung abgleichen
550 Verarbeitung intern abgebrochen Abgleichen und anschließend nach einer begrenzten Richtlinie wiederholen

Diese Tabelle dient nur der Einordnung und ersetzt nicht die Antwort. Bewahren Sie die unbearbeitete Beschreibung, sämtliche details und alle extensions auf. Das Ministerium veröffentlicht keinen stabilen, vollständigen Katalog, der jedes mögliche Detail zu 430 oder 450 einem XPath zuordnet. Behandeln Sie deshalb auch neue und unbekannte Zustände, statt aus den heutigen Beschreibungen einen anfälligen Parser zu bauen.

Der Sitzungsstatus bleibt wichtig, allerdings aus einem anderen Grund. Ein Fehler beim Sitzungsarchiv, bei der Entschlüsselung oder beim Paket sowie eine Zeitüberschreitung können die zugehörigen Rechnungen abbrechen. Prüfen Sie nach der Verarbeitung einer Sitzung deren Erfolgs- und Fehlerzähler und anschließend die einzelnen Rechnungsstatus. Bei einer gemischten Stapelverarbeitung führt der Endpunkt für fehlgeschlagene Rechnungen am schnellsten zu den Diagnosedaten.

Wie sollten Sie FA(3)-XML vor dem Upload prüfen?

Seit dem 1. Februar 2026 ist FA(3) das einzige Schema für strukturierte Rechnungen, das bei neuen Übermittlungen akzeptiert wird. Das gilt auch für Korrekturen von Rechnungen, die ursprünglich unter FA(1) oder FA(2) ausgestellt wurden. Öffnen Sie die Sitzung mit systemCode: "FA (3)", schemaVersion: "1-0E" und value: "FA" und validieren Sie gegen das maßgebliche FA(3)-XSD.

Validieren Sie exakt die Bytes, deren Hashwert Sie bilden und die Sie verschlüsseln werden. Der Leitfaden des Ministeriums zur Rechnungsprüfung verlangt XML 1.0, UTF-8 ohne Byte Order Mark, das bei Sitzungsbeginn angegebene Schema, keine widersprechende Angabe zur Zeichenkodierung, keine Verarbeitungsanweisungen und keine Zeichen aus den ausdrücklich nicht empfohlenen Unicode-Bereichen. Sobald Sie eine optionale Struktur aufnehmen, werden deren Pflichtfelder dennoch obligatorisch.

Bei einer Rails-Integration mit Nokogiri kann eine lokale Vorprüfung so beginnen:

schema = Nokogiri::XML::Schema(File.read("schemat_FA(3)_v1-0E.xsd"))
bytes = File.binread("invoice.xml")

raise "UTF-8 BOM is not allowed" if bytes.start_with?("\xEF\xBB\xBF".b)

document = Nokogiri::XML(bytes) { |config| config.strict.nonet }
errors = schema.validate(document)

raise errors.map(&:message).join("\n") if errors.any?

Damit erkennen Sie fehlerhaftes XML und XSD-Verstöße. Die vollständige serverseitige Validierung wird dadurch nicht nachgebildet. Ergänzen Sie mindestens anwendungsspezifische Prüfungen für:

  • Verkäuferidentität und die von Ihrem Nummerierungssystem vorgesehene Rechnungsnummer;
  • Datumswerte, insbesondere dass P_1 nicht nach der Annahme durch KSeF liegt;
  • bedingte FA(3)-Strukturen und fachliche Rechenregeln;
  • Grenzen für Dateigröße und Rechnungszahl je Sitzung;
  • die Berechtigung für Anhänge, falls zutreffend;
  • Größe und SHA-256-Hashwerte der unverschlüsselten und verschlüsselten Bytes, die in den Metadaten gesendet werden;
  • die Verschlüsselung mit dem aktuellen öffentlichen KSeF-Schlüssel und den dokumentierten Algorithmen.

Behalten Sie die fachliche Validierung auch bei, wenn KSeF 200 zurückgibt. In den Fragen und Antworten zu KSeF erklärt das Ministerium, dass das System eine Rechnung mit Rechenfehlern oder einer falschen, aber prüfsummengültigen NIP des Geschäftspartners annehmen kann. Die serverseitige Annahme beweist, dass KSeF die strukturierte Rechnung angenommen hat, nicht dass Ihre Buchhaltungsdaten korrekt waren.

TEST, DEMO und Produktivumgebung weisen außerdem unterschiedliche Sachverhalte nach. TEST verwendet anonymisierte Daten und hat keine rechtliche Wirkung. DEMO nutzt eine echte Authentifizierung, hat aber ebenfalls keine rechtliche Wirkung. Die Produktivumgebung dagegen schon. Manche Prüfungen, darunter ausgewählte Prüfungen der NIP-Prüfsumme, finden ausschließlich in der Produktivumgebung statt. Ein erfolgreicher Test in TEST zeigt, dass Ihre Integration in TEST funktioniert. Er garantiert keinen Erfolg in der Produktivumgebung.

Wie diagnostizieren Sie Status 450 ohne Ratespiel?

Behandeln Sie 450 als serverseitigen Befund zur Rechnungssemantik und sichern Sie genügend Eingabedaten, um ihn exakt zu reproduzieren. Ändern Sie nicht wahllos Felder, bis der Fehler verschwindet.

  1. Speichern Sie das vollständige Statusobjekt einschließlich aller von KSeF zurückgegebenen Details.
  2. Suchen Sie den unveränderlichen Quelldatensatz, aus dem die Rechnung erzeugt wurde.
  3. Gleichen Sie dessen gespeicherten XML-Hashwert mit den Bytes ab, die unter der Rechnungsreferenz übermittelt wurden.
  4. Wenden Sie die lokalen XSD- und Fachvalidatoren erneut auf diesen Quelldatensatz an.
  5. Ordnen Sie das zurückgegebene Detail dem FA(3)-Feld und dem Wert des Quellsystems zu, der dieses Detail verursacht hat.
  6. Korrigieren Sie Quelle oder Zuordnung, erzeugen Sie neues XML und validieren Sie die neuen Bytes vollständig von vorn.

Ein abgelehntes XML-Dokument wurde nicht ausgestellt. Nach Angabe des Ministeriums müssen Sie es reparieren und ein gültiges XML-Dokument übermitteln. Es ist keine Korrektur einer bereits angenommenen Rechnung. Dieser Unterschied ist für die Wiederholungslogik wichtig: Eine Reparatur erzeugt einen neuen Übermittlungsversuch. Die Geschäftsidentität und die Nachweiskette müssen dennoch auf den fehlgeschlagenen Versuch zurückverweisen.

Wenn dieselbe Nutzlast in TEST akzeptiert wird, aber in der Produktivumgebung fehlschlägt, prüfen Sie umgebungsspezifische Unterschiede bei Autorisierung, Berechtigungen, Identität und Validierung, bevor Sie einen lokalen Validator lockern. Senden Sie niemals eine Wegwerfrechnung in die Produktivumgebung, nur um das Verhalten zu testen: Ein erfolgreiches Ergebnis hat rechtliche Wirkung.

Warum müssen Sie Duplikatstatus 440 abgleichen?

KSeF erkennt ein Duplikat anhand von drei Geschäftsfeldern: NIP des Verkäufers (Podmiot1:NIP), Rechnungsart (RodzajFaktury) und Rechnungsnummer (P_2). Der dokumentierte Eindeutigkeitszeitraum dauert zehn volle Jahre nach Ablauf des Jahres, in dem die Rechnung ausgestellt wurde.

440 beweist daher nicht, dass die XML-Bytes identisch sind. Der Status bedeutet, dass KSeF bereits eine Rechnung mit derselben Geschäftsidentität angenommen hat. Er kann originalSessionReferenceNumber und originalKsefNumber enthalten. Nutzen Sie diese Angaben.

So gleichen Sie den Vorgang ab:

  1. Ermitteln Sie die ursprüngliche KSeF-Nummer und Sitzungsreferenz aus den Statuserweiterungen.
  2. Vergleichen Sie die ursprüngliche Rechnung mit der vorgesehenen Quelltransaktion.
  3. Rufen Sie die ursprüngliche UPO ab und prüfen Sie sie.
  4. Kennzeichnen Sie den lokalen Versuch als mit dieser angenommenen Rechnung abgeglichen.
  5. Eskalieren Sie den Fall, falls die angenommene Rechnung nicht der vorgesehenen Geschäftstransaktion entspricht.

Erhöhen Sie P_2 nicht nur deshalb, damit der Fehler verschwindet. Wenn die ursprüngliche Anfrage erfolgreich war, aber ihre Antwort verloren ging, kann die geänderte Nummer eine zweite rechtlich wirksame Rechnung erzeugen. Trennen Sie die Geschäftsnummerierung von den Transportversuchen: Eine Rechnung kann mehrere Versuchsdatensätze haben. Eine Wiederholung darf jedoch nicht unbemerkt ein neues Geschäftsdokument erfinden.

Damit wird außerdem ein wichtiges Nebenläufigkeitsrisiko sichtbar. Wenn getrennte Teams oder ausstellende Einheiten dieselbe Verkäufer-NIP verwenden, müssen sie ihre Rechnungsnummern koordinieren. Die lokale Eindeutigkeit in jeder einzelnen Anwendung genügt für den globalen Duplikatschlüssel von KSeF nicht.

Bei welchen KSeF-Fehlern dürfen Sie einen Versuch sicher wiederholen?

Ob und wie Sie einen Versuch wiederholen, hängt zunächst von der Fehlerebene ab.

Wiederholen Sie deterministische Eingabefehler nicht unverändert. XML-/XSD-Fehler, abweichende Größen oder Hashwerte, Berechtigungsprobleme, fehlende Berechtigungen für Anhänge, Entschlüsselungsfehler und der semantische Status 450 müssen behoben werden. Dieselben Bytes unter denselben Bedingungen erneut zu senden, erzeugt nur Rauschen, belastet Ihre Limits und liefert keine neuen Erkenntnisse.

Wiederholen Sie Duplikatstatus 440 nicht blind. Gleichen Sie ihn mit der ursprünglich angenommenen Rechnung ab.

Halten Sie bei HTTP 429 die gesamte Dauer aus Retry-After ein. Die KSeF-Limits überlagern Zeitfenster von einer Sekunde, einer Minute und einer Stunde. Weitere Aufrufe während einer Sperre können diese verlängern. Koordinieren Sie Worker, die denselben Authentifizierungskontext und dieselbe IP-Adresse verwenden. Fügen Sie einen zufälligen zeitlichen Versatz hinzu, bevor Sie aufgestaute Arbeit freigeben, und fragen Sie GET /rate-limits zur Laufzeit ab, statt veröffentlichte Standardwerte für Ihr Konto vorauszusetzen.

Bei Zeitüberschreitungen und HTTP 5xx kann das Ergebnis unklar sein. Die Antwort kann verloren gehen, nachdem der Server die Anfrage bereits gespeichert hat. Die OpenAPI-Spezifikation für die Produktivumgebung dokumentiert keinen vom Client bereitgestellten Idempotenzschlüssel für den Online-Versand oder das Schließen eines Stapels. Die folgenden Punkte sind daher technische Empfehlungen und keine Garantie von KSeF:

  • Speichern Sie Sitzungsreferenz, Rechnungshashwert, Größe und Zeitstempel des Versuchs vor dem Versand.
  • Prüfen Sie nach einem unklaren Online-Versand dieselbe Sitzung und gleichen Sie deren Rechnungsliste ab, bevor Sie erneut übermitteln.
  • Fragen Sie die betreffende Sitzung nach einem unklaren Stapelabschluss ab. Schließen Sie sie nur erneut, wenn sie weiterhin geöffnet ist.
  • Wenn der Abgleich kein gespeichertes Ergebnis findet, verwenden Sie exponentiell wachsende, begrenzte Warteintervalle mit zufälligem Versatz.
  • Beenden Sie die Wiederholungen nach einem festen Budget und geben Sie den Versuch zusammen mit allen Belegen zur manuellen Prüfung weiter.

Rechnungsstatus 550 fordert ausdrücklich zu einem erneuten Versuch auf. Doch auch „wiederholbar“ bedeutet nicht „unbegrenzt wiederholen“. Bewahren Sie die Diagnosedaten auf, gleichen Sie den Versuch ab und wenden Sie dieselbe begrenzte Wiederherstellungsrichtlinie an. Setzen Sie bei Status 500 einen fachlichen Verarbeitungscode nicht mit HTTP 500 gleich. Bewahren Sie den Namensraum auf und untersuchen Sie den Fehler, bevor Sie entscheiden.

Auch Statusabfragen müssen zurückhaltend erfolgen. Fragen Sie bei 100 und 150 weiter ab, verlängern Sie die Abstände zwischen den Abfragen und beenden Sie den Vorgang bei einem Endstatus. Die feste Abfrageschleife im Sekundentakt eines Beispiel-Clients ist keine offizielle Verarbeitungs-SLA.

Welche Belege sollte eine Produktivintegration aufbewahren?

Bei einer erfolgreichen Rechnung reichen die Belege über einen grünen Status im Dashboard hinaus. Speichern Sie dauerhaft die Daten, die die Geschäftstransaktion mit dem von KSeF angenommenen Inhalt verbinden:

  • unveränderlicher Quelldatensatz sowie Versionen der Zuordnung und des Schemas;
  • exakter Hashwert und Byte-Größe des unverschlüsselten XML;
  • Verschlüsselungsmetadaten sowie Hashwert und Größe der verschlüsselten Daten;
  • beobachtete Umgebung und API-Version;
  • Sitzungs- und Rechnungsreferenznummern;
  • Statusverlauf mit Zeitstempeln, Beschreibungen, Details und Erweiterungen;
  • KSeF-Rechnungsnummer;
  • UPO-XML und dessen SHA-256-/Base64-Integritätswert;
  • Verknüpfungen zwischen Geschäftsrechnung, sämtlichen Übermittlungsversuchen und dem angenommenen Ergebnis.

Eine UPO für eine Rechnung ist erst verfügbar, nachdem diese Rechnung erfolgreich verarbeitet wurde. Sie kann abgerufen werden, solange die Sitzung noch geöffnet ist. Zusammengefasste Sitzungs-UPOs erscheinen nach dem Schließen und enthalten nur die angenommenen Rechnungen. Eine Sitzung mit gemischten Ergebnissen kann deshalb gleichzeitig eine UPO und fehlgeschlagene Rechnungen enthalten. Verwenden Sie „Sitzung hat UPO“ nicht als Kurzform für „alle Rechnungen waren erfolgreich“.

KSeF kann in einer Statusantwort eine temporäre URL zum Herunterladen der UPO bereitstellen. Sie läuft ab und ist nicht der dauerhaft aufzubewahrende Beleg. Laden Sie das signierte XML herunter, prüfen Sie den vom authentifizierten Endpunkt zurückgegebenen Wert x-ms-meta-hash und bewahren Sie den Beleg gemäß Ihrer Nachweisrichtlinie auf.

So verarbeitet KSeF Kit den Übermittlungszyklus

KSeF Kit ist ein separates Produkt für Teams, die Stripe-Rechnungen an das polnische KSeF übermitteln. Der dokumentierte Ablauf der Rechnungsübermittlung folgt denselben Grenzen, die dieser Leitfaden empfiehlt: KSeF Kit speichert Quelldaten als unveränderlichen Datensatz, ordnet sie FA(3) zu, übermittelt sie über eine verschlüsselte Online-Sitzung, fragt das Ergebnis ab, zeichnet einzelne Übermittlungsversuche auf, setzt das Warten anhand gespeicherter Referenzen fort, speichert die UPO und schreibt die KSeF-Nummer zurück nach Stripe.

Dadurch müssen Sie eine Ablehnung weiterhin verstehen. Sie erhält jedoch einen dauerhaften Platz in einem Ablauf mit expliziten Zuständen, statt in einer einzelnen fehlgeschlagenen HTTP-Anfrage zu verschwinden. Teams, die ihre eigene Integration entwickeln, können demselben Aufbau folgen: unveränderliche Eingaben, explizite Versuche, fortsetzbare Referenzen, vorgangsbezogene Statusbehandlung und Abgleich vor einer erneuten Übermittlung.

Wenn Stripe Ihre Rechnungsquelle ist und Sie diesen Ablauf lieber betreiben als selbst entwickeln möchten, lesen Sie, wie KSeF Kit Umgebungen verbindet, und die zugehörige Referenz zur Fehlerbehebung. Unabhängig von Ihrer Entscheidung gilt in der Produktivumgebung dieselbe Regel: Ein Code ohne den zugehörigen Vorgang ist keine Diagnose, und eine Wiederholung ohne Abgleich ist kein Wiederherstellungsplan.

Verwandte Artikel

Bereit, smarter einzustellen?

30 Tage kostenlos testen. Wenn Sie vor Ablauf kündigen, zahlen Sie nichts. Richten Sie Ihre erste Recruiting-Pipeline in wenigen Minuten ein.

Kostenlos starten