# BR-CL-18: Use a permitted VAT category code on each line item

The line category in `cac:ClassifiedTaxCategory/cbc:ID` must be a permitted code such as `S`, `Z` or `E`. An internal code like `SR` is rejected.

- Layer: EN 16931
- Severity: fatal (the document is invalid)
- Topics: VAT, Code lists
- Official definition: https://docs.peppol.eu/poacc/billing/3.0/rules/ubl-tc434/BR-CL-18/
- Explanation last updated: 2026-09-24

## The short answer

`BR-CL-18` fails when the `cbc:ID` in a line item's `cac:ClassifiedTaxCategory` is outside the permitted VAT category codes. Replace it with the code for the category the line was really taxed in; in the recorded example the line says `SR` and the Standard rated code is `S`.

While the line carries an unrecognised code it belongs to no category, so the breakdown that should total it no longer matches and the category rules report that too.

## What the rule checks

The rule runs on every `cbc:ID` inside a `cac:ClassifiedTaxCategory`, which in these documents is the item of each `cac:InvoiceLine` or `cac:CreditNoteLine`. Breakdowns and document-level allowances and charges fall under `BR-CL-17` instead.

It accepts the same ten codes as the breakdown rule: `S`, `Z`, `E`, `AE`, `K`, `G`, `O`, `L`, `M` and `B`. Surrounding spaces are trimmed, but the comparison is case-sensitive, and a lower-case `s` on the line was rejected when tried.

An empty `cbc:ID` on the line fails here, not under `BR-CO-04`, which only asks for the element to exist. When tried, it also brought `PEPPOL-EN16931-R008`.

A listed code is accepted even when it is the wrong category for the item. Consistency with the breakdown is tested by the category rules, not by this one.

| Term | Meaning | UBL element |
|---|---|---|
| BT-151 | Invoiced item VAT category code | `cac:InvoiceLine/cac:Item/cac:ClassifiedTaxCategory/cbc:ID (cac:CreditNoteLine/cac:Item/cac:ClassifiedTaxCategory/cbc:ID in a credit note)` |

## How an integration ends up here

Possible causes, from the shape of the rule rather than from measured usage:

- The item tax code from the product master, such as `SR` or `ZR`, is copied onto the line without translation.
- The breakdown is built through a translation table but the lines are not, so the two carry different code sets.
- A description such as `Standard` or a rate such as `20` is written in the code field.
- A library or template produces the code in lower case.

## How to fix it

1. Use the finding location to find the line and its current code.
2. Translate it to the permitted code for the category the item was taxed in, using the same mapping as the breakdown.
3. Confirm that the line now falls into a breakdown with the same category and rate, so that breakdown taxable amount matches its lines.
4. Reject unmapped item tax codes at export time.

## Before and after

These are fragments, not complete documents. The complete synthetic documents they come from are linked below.

Fragment of the failing invoice: the line is coded SR while its breakdown is coded S

```xml
<cac:TaxSubtotal>
  <cbc:TaxableAmount currencyID="GBP">25.00</cbc:TaxableAmount>
  <cbc:TaxAmount currencyID="GBP">5.00</cbc:TaxAmount>
  <cac:TaxCategory>
    <cbc:ID>S</cbc:ID>
    <cbc:Percent>20</cbc:Percent>
    <!-- tax scheme omitted from this fragment -->
  </cac:TaxCategory>
</cac:TaxSubtotal>

<cac:InvoiceLine>
  <cbc:ID>1</cbc:ID>
  <cbc:InvoicedQuantity unitCode="C62">2</cbc:InvoicedQuantity>
  <cbc:LineExtensionAmount currencyID="GBP">25.00</cbc:LineExtensionAmount>
  <cac:Item>
    <cbc:Name>Example service</cbc:Name>
    <cac:ClassifiedTaxCategory>
      <cbc:ID>SR</cbc:ID>
      <cbc:Percent>20</cbc:Percent>
      <cac:TaxScheme>
        <cbc:ID>VAT</cbc:ID>
      </cac:TaxScheme>
    </cac:ClassifiedTaxCategory>
  </cac:Item>
  <!-- price omitted from this fragment -->
</cac:InvoiceLine>
```

Fragment of the corrected invoice: the line uses the Standard rated code S

```xml
<cac:InvoiceLine>
  <cbc:ID>1</cbc:ID>
  <cbc:InvoicedQuantity unitCode="C62">2</cbc:InvoicedQuantity>
  <cbc:LineExtensionAmount currencyID="GBP">25.00</cbc:LineExtensionAmount>
  <cac:Item>
    <cbc:Name>Example service</cbc:Name>
    <cac:ClassifiedTaxCategory>
      <cbc:ID>S</cbc:ID>
      <cbc:Percent>20</cbc:Percent>
      <cac:TaxScheme>
        <cbc:ID>VAT</cbc:ID>
      </cac:TaxScheme>
    </cac:ClassifiedTaxCategory>
  </cac:Item>
  <!-- price omitted from this fragment -->
</cac:InvoiceLine>
```

The failing invoice has `SR` in the line item's `cac:ClassifiedTaxCategory/cbc:ID`; the corrected one has `S`, and nothing else differs. Two breakdown rules also fire, because with `SR` on the only line nothing in the document is Standard rated while the breakdown still is. `BR-S-01` objects to a Standard rated breakdown with no Standard rated line, allowance or charge behind it. `BR-S-08` finds no Standard rated line at 20% to account for the 25.00 taxable amount. Correcting the code clears all three.

### What the validator reported

- The failing invoice reports **BR-CL-18**, [BR-S-01](https://ironfang.uk/docs/finance/rules/BR-S-01.md) and [BR-S-08](https://ironfang.uk/docs/finance/rules/BR-S-08.md). The corrected document passes every layer with no findings.
  - [Download the failing XML](https://ironfang.uk/finance/rule-examples/BR-CL-18-invalid.xml)
  - [Download the corrected XML](https://ironfang.uk/finance/rule-examples/invoice-minimal.xml)

Recorded on phive 12.1.0 / phive-rules-peppol 4.5.6 / Saxon-HE 12.10, the engine behind the free validator, using synthetic data. A recorded result is regression evidence for these documents; it is not a certification.

## Where it applies

- Applies to UBL `Invoice` and `CreditNote`. In a credit note the line is `cac:CreditNoteLine`; with `SR` on its line it reported the same three rules when tried.
- The companions depend on the category the line should have had. When tried, `ZR` on the Zero rated line of a mixed invoice brought `BR-Z-08` instead.
- If the breakdown carries the same wrong code, the category rules fall silent and `BR-CL-17` is reported beside this rule instead.
- Reported by the EN 16931 layer; the Peppol layer passes the recorded example.

## Related rules

- [BR-CL-17 applies the same code list to the VAT breakdown and document-level allowances and charges](https://ironfang.uk/docs/finance/rules/BR-CL-17.md)
- [BR-CO-04 requires the line category code that this rule checks](https://ironfang.uk/docs/finance/rules/BR-CO-04.md)
- [BR-S-01 fires with this rule when the miscoded line leaves a Standard rated breakdown unsupported](https://ironfang.uk/docs/finance/rules/BR-S-01.md)
- [BR-S-08 recalculates the Standard rated taxable amount without the miscoded line](https://ironfang.uk/docs/finance/rules/BR-S-08.md)

## Scope and source

Written for Peppol BIS Billing 3.0.21 (May 2026), EN 16931 1.3.16, as applied to UBL 2.1 Invoice and CreditNote documents. Other profiles, syntaxes and releases can define this identifier differently. Guidance version 2026-09-24.1: source checked 2026-09-24, explanation last updated 2026-09-24.

[The official definition of BR-CL-18](https://docs.peppol.eu/poacc/billing/3.0/rules/ubl-tc434/BR-CL-18/) carries the normative wording and test. This page is our explanation of it, not a copy.

Guidance does not change the engine verdict. Fixing this finding does not mean the document passes every layer, and validation does not certify legal or tax compliance or transmit a document over Peppol.

## Links

- [This rule as a web page](https://ironfang.uk/docs/finance/rules/BR-CL-18)
- [Free Peppol invoice validator](https://ironfang.uk/tools/peppol-validator)
- [Rule index](https://ironfang.uk/docs/finance/rules.md)
- [Ironfang Finance API docs](https://ironfang.uk/docs/finance)
- The same rule is available to MCP clients as the tool `finance.rule.get` on https://mcp.ironfang.uk/mcp
