How to read KSeF error codes without guessing?
A KSeF response consists of three layers: the HTTP status, the exceptionCode, and the invoice status. Understanding these layers helps determine whether a message requires technical XML validation fixes or accounting action.

KSeF (Poland's national e-invoicing system) answers with a number and one sentence, and within the same minute someone has to choose between three very different actions: fix the XML, retry the request, or hand the case to accounting. Three decisions, three costs, three deadlines.
Under the current act, penalties under Article 106ni of the VAT Act apply from 1 January 2027. On 16 September 2026 the Ministry of Finance announced it will move them to 1 January 2028; that is a bill not yet passed, and it moves only the penalties, not the obligation to use KSeF. Either way, an invoice that never reached the system stops being a technical problem and becomes a financial one. If you run a Polish entity or a Polish subsidiary, the thing worth building in the meantime is a procedure for reading gateway messages — not a habit of pasting codes into a search box.
This is the map: how a KSeF response is structured, what each code family covers, which codes are safe to simply retry, and where the handover from engineering to accounting actually sits. The complete list of codes is published by the Ministry of Finance in the API documentation; here we cover the ones you will meet most often.
A KSeF message has three layers, not one
An error number without context is useless. The same 21405 can mean a malformed query parameter one day and a badly mapped ERP field the next. Read every response on three levels:
HTTP status — whether the gateway accepted the request at all.
exceptionCodeandexceptionDescription— the specific reason on the KSeF side.Invoice or session status — whether the document already carries a KSeF number, or does not exist in the system yet.
Only together do these say whose problem it is. Layers one and two belong to the integration. Layer three belongs to accounting, because that is where the decision about a correcting invoice is made.
Two identifiers deserve to be logged every single time: the operation's referenceNumber and the response's traceId. Without them, a ticket to the Ministry of Finance or to your software vendor is an anecdote rather than a report.
Code families: what the leading digits tell you
KSeF 2.0 numbering is not arbitrary. The leading digits point at the subsystem that rejected the request — enough to route the case to the right person in seconds.
| Family | Area | Who fixes it |
|---|---|---|
9xxx | signature and authorisation document | integrator |
211xx | authentication, sessions, invoice retrieval, export | integrator |
212xx | batch package and its parts | integrator |
213xx | authorisation and access tokens | company administrator |
214xx | document and input-data validation | integrator or invoice issuer |
250xx | KSeF certificates | company administrator |
260xx | KSeF tokens | company administrator |
Rule of thumb: anything below 214xx is usually configuration, not the invoice. Editing a document in response to an authentication error is the most common way to lose an hour.
HTTP statuses: the first branch
| Status | Meaning | Response |
|---|---|---|
| 400 | malformed request or input-data validation failure | read exceptionCode and the errors list in the payload |
| 401 | authentication missing or invalid | token, certificate, session validity |
| 403 | insufficient permissions or disallowed context | NIP (Polish tax ID) context and the permission scope for that operation |
| 410 | the operation has expired and is no longer available | start the process again |
| 415 | operation type not allowed in this submission mode | switch modes (see the case below) |
| 429 | API rate limit exceeded | Retry-After, queueing, backoff — do not touch the invoice |
| 5xx | failure on the KSeF infrastructure side | capture traceId, retry per your retry policy |
Note that 410 and 415 also appear as invoice processing statuses inside a session, not as the HTTP code of the response — the case below is one of those statuses. The most expensive misreading in this table is 429. Under real API limits it is easy to treat it as a document rejection and start "fixing" a perfectly valid invoice. Current limits are published in the CIRF/MF documentation.
The most frequent codes and what they mean
Signature and authorisation document (9xxx)
| Code | Message | Action |
|---|---|---|
| 9101 | Invalid document | check the document used in the signing process |
| 9102 | Signature missing | the required signature was not attached |
| 9103 | Too many signatures | verify the signature count for this document type |
Sessions, invoices and export (211xx)
| Code | Message | Action |
|---|---|---|
| 21111 | Invalid authorisation challenge | challenge, encryption and timing in the auth flow |
| 21115 | Invalid certificate | validity and compliance with KSeF requirements |
| 21117 | Invalid subject identifier for the context type | the NIP does not match the selected context type |
| 21155 | Invoice limit for the session exceeded | close the session and open a new one |
| 21157 | Invalid package part size | declared part size ≠ actual file |
| 21161 | Too many package parts | rebuild the batch package |
| 21164 | Invoice with the given identifier does not exist | KSeF number, subject context, retrieval permissions |
| 21165 | Invoice not available yet | not an error — wait and poll again |
| 21166 | Technical correction unavailable | it has most likely already been processed |
| 21167 | Invoice status does not allow a technical correction | an accounting case, not an integration one |
| 21173 | No session with that reference number | reference number or environment (test vs. production) |
| 21175 | Query result does not exist | export reference, or the result's availability window expired |
| 21178 | No UPO found for the given criteria | the UPO (official receipt confirmation) is issued after the session closes — retry later |
| 21180 | Session status does not allow the operation | session closed or cancelled |
| 21181 | Invalid invoice export request | export criteria and subject context |
| 21182 | Concurrent export limit reached | reduce parallel exports |
| 21183 | Filter range outside the available data range | date range and date type |
Batch package (212xx)
| Code | Message | Action |
|---|---|---|
| 21205 | Package must not be empty | not all declared parts were uploaded |
| 21208 | Upload or finish timeout exceeded | the session may have been cancelled — repeat the process |
| 21217 | Invalid character encoding | UTF-8, no BOM |
Authentication and authorisation (213xx)
| Code | Message | Action |
|---|---|---|
| 21301 | Not authorised | token revoked, or the authentication operation never completed |
| 21304 | Not authenticated | no operation with that reference number in this environment |
| 21308 | Attempt to use the authorisation methods of a deceased person | the entity's authentication path has to change |
Document and input validation (214xx)
| Code | Message | Action |
|---|---|---|
| 21401 | Document does not conform to the XSD schema | the classic "invoice error": FA(3) structure, mandatory fields, encoding |
| 21402 | Invalid file size | declared size ≠ actual content length |
| 21403 | Invalid file hash | how the hash is computed |
| 21405 | Input-data validation error | read the details, not the number — the code alone says nothing |
| 21406 | Signature and authentication type conflict | auth method vs. certificate type |
| 21418 | Invalid continuation token format | never edit the pagination token by hand |
| 21470 | Unknown or withdrawn key identifier | fetch the current public key for your environment |
Certificates and tokens (250xx, 260xx)
| Code | Message | Action |
|---|---|---|
| 25001 | CSR data cannot be retrieved for this authentication method | change the authentication method |
| 25002 | Certificate request cannot be submitted for this method | as above |
| 25003 | CSR data does not match the authentication vector | subject data inside the CSR |
| 25004 | Invalid CSR format or signature | request format and signing algorithm |
| 25005 | Certificate request with that reference number does not exist | reference number and environment |
| 25006 | Certificate request limit reached | clean up outstanding requests |
| 25007 | Held-certificate limit reached | revoke unused certificates |
| 25010 | Invalid key type or length | key requirements in the certificate docs |
| 25011 | Invalid CSR signing algorithm | algorithm and hash function |
| 26001 | Cannot grant a token permissions the subject does not hold | fix the subject's permissions first |
| 26002 | Cannot issue a token for the current context type | tokens are issued only in permitted contexts |
The KSeF 2.0 catalogue is larger than the list above; the source of truth remains the API documentation at api.ksef.mf.gov.pl and the CIRF/MF integrator guide.
Same document, two different answers: a case from our own rollout
On 10 September 2026, on the Ministry's test environment, we were testing invoices with attachments. The same invoice submitted through an interactive session came back with processing status 415 and a message stating that an invoice with an attachment cannot be sent that way. The same invoice in a batch session was accepted. And the same interactive session accepted the same invoice once the attachment node was removed.
The uncomfortable but useful conclusion: some messages do not say "this document is wrong" — they say "not through this channel". Anyone who had started by editing the XML would have been editing a valid file. The differences between modes are documented in the batch session guide.
An error does not always mean the invoice is missing
The costliest mistakes happen on the other side of the line: when the invoice already has a KSeF number.
Acceptance by the gateway means conformity with the logical structure, and nothing more. KSeF does not check VAT treatment, commercial substance, or arithmetic. An invoice with the wrong rate can pass technical validation without a single message.
The practical consequence: a document that received a KSeF number cannot be withdrawn or overwritten from your sales system. What remains is a correcting invoice. A technical correction applies only to an offline invoice that KSeF rejected — you cannot use it to fix a document that already has a KSeF number. That is an accounting decision, not an integration one, which is exactly why the third layer of the message must never be skipped.
Duplicates are a separate trap. KSeF identifies them from a combination of seller data, invoice type and document number, and keeps uniqueness for years — resending "just in case" is not a neutral act.
Checklist: what to capture for every error
HTTP status of the response.
exceptionCodeand the fullexceptionDescription.referenceNumberof the operation (session, request, export).traceIdfrom the response.Environment: test or production.
Invoice status: was a KSeF number assigned.
UTC timestamp — with rate limits and sessions, the second matters.
Those seven fields turn "it doesn't work on our side" into something that can actually be investigated. Reporting paths are described on the integrator support page.
Summary
KSeF error codes look like a purely technical topic, yet they settle accounting questions: whether the invoice exists, whether the deadline was met, whether a correction is required. Three layers of the response, the family map and seven checklist fields are enough to stop guessing.
Biurko translates the 28 most common gateway codes into one plain sentence and one suggested action and shows the rest as the Ministry's own text, and it retries transient failures automatically (up to three attempts; after a 429 it waits the time the gateway names). Try Biurko — every new company gets 14 days of the TEAM plan without a card and see what submitting to KSeF looks like when nobody has to read numbers.
FAQ
What does KSeF error 21401 mean? The document does not conform to the XSD schema. In practice it usually comes down to the FA(3) structure, an empty mandatory field, or encoding other than UTF-8 without BOM. The number itself does not identify the field — the validator message returned alongside it does.
Does a 429 error mean my invoice was rejected? No. It signals that the API rate limit was exceeded and concerns the integration only. The invoice is fine. The fix is reading the Retry-After header, queueing requests and applying exponential backoff — not editing the document.
If KSeF accepts an invoice, is the invoice correct? No. The system validates conformity with the logical structure and the technical soundness of the file. It does not verify VAT settlement or arithmetic. An invoice with a substantive error can receive a KSeF number and need a correction later.
Where is the official list of KSeF error codes? The source of truth is the OpenAPI contract and the API 2.0 documentation on api.ksef.mf.gov.pl, together with the CIRF/MF repository holding the integrator guide and the changelog, where the Ministry publishes newly added codes.
What if an invoice already has a KSeF number but contains an error? It cannot be deleted or overwritten. The route is a correcting invoice; a technical correction applies only to an offline invoice that KSeF rejected.
Tags
Previous article
How much does an accountant cost for a Polish JDG?
Next article
How will the 2027 minimum wage affect your ZUS in Poland?