Skip to content

hr.tax_line_inconsistent

HTTP 400 type: validation_error param: vat[0].amount
{
"error": {
"type": "validation_error",
"code": "hr.tax_line_inconsistent",
"message": "25.00% of 10.00 is 2.50, but this line says 5.50. Tax may differ from the rate applied to the base only by the rounding of the individual items it sums (0.02, or 1% of the tax, whichever is larger) — this is further out than that. Check which base the rate belongs to; the Tax Administration does not verify this and will issue a JIR for it.",
"param": "vat[0].amount",
"upstream": null,
"doc_url": "https://docs.fiskhub.com/errors/hr.tax_line_inconsistent"
}
}

upstream is null because there is no upstream code. This check is ours.

What happened

A line in vat, consumption_tax or other_taxes carries an amount that the declared rate applied to the declared base could not produce.

Why this is refused when the Tax Administration would accept it

Because it would accept it. Send a receipt whose VAT reads 25% of 10.00 = 5.50 and the message is well-formed, the signature verifies, and a JIR comes back. Nothing fails. The receipt is simply wrong in your books, and it is wrong permanently: once a sale is fiscalized it cannot be amended, only reversed with a storno and reissued.

That makes the moment the request arrives the last cheap opportunity to notice. A 400 costs one retry. A JIR on a wrong filing costs a storno, a new receipt, and a discrepancy that surfaces in an audit rather than in a log.

The same reasoning covers the neighbouring failure: a VAT-registered company filing a receipt with no vat at all. See companies on default_vat_rate.

The tolerance, and why there is one

amount is not required to equal base × rate exactly. It has to be within

  • 0.02, or
  • 1% of the expected tax, whichever is larger.

A real receipt is built from line items, each rounded to the cent. The aggregate tax line you send is their sum, so it legitimately drifts from round(base × rate) by up to half a cent per item — a 40-item basket can land 20 cents from the naive product and still be correct to the cent on every line.

Refusing that would stop a sale at a device with a customer in front of it, which is a far worse outcome than a two-cent discrepancy in a report. So the band is set wide enough that no plausible per-item rounding can trip it, and the errors it does catch — a rate applied to the wrong base, an amount typed by hand, a sign flip — are out by tens of percent.

BaseRateExpectedAllowed
"17.60""25.00"4.404.384.42
"100.00""25.00"25.0024.7525.25
"1000.00""25.00"250.00247.50252.50

A zero rate gets no tolerance. Nothing rounds into existence from 0%, so "0.00" must carry exactly "0.00" of tax.

Should you retry?

Not unchanged. Correct the line first — the same body will be refused again.

The fix

Check which base the rate belongs to. The commonest cause is a rate applied to the receipt total rather than to the net amount:

// Wrong — 25% of the 12.50 total, reported against a 10.00 base
{ "total": "12.50", "vat": [{ "rate": "25.00", "base": "10.00", "amount": "5.50" }] }
// Right — the total split into base and tax
{ "total": "12.50", "vat": [{ "rate": "25.00", "base": "10.00", "amount": "2.50" }] }
SymptomCause
Tax is ~2× expectedThe rate was applied to the VAT-inclusive total, not the base.
Tax is expected ÷ 1.25Base and total were swapped.
Tax is negative, base positiveA storno built by negating only one field. Negate both.
A "0.00" line carrying taxThe rate was omitted and defaulted to zero. Send the rate applied.

Let us compute it for you

If every sale from a device is single-rate, do not send vat at all. Set default_vat_rate on the company and the total is split for you — one rounding, on the base, with the tax as the remainder, so base + amount equals the total exactly by construction rather than by arithmetic you have to get right.

A receipt spanning two rates must still send its own array: one rate cannot describe two.