Back to all articles
  • calculation
  • compliance

Fifteen steel codes where we cannot reconcile the two CBAM acts

7 min read

Two implementing regulations sit underneath every CBAM steel calculation. One gives you the default emissions to use when you have no verified supplier data. The other gives you the free-allocation benchmark you subtract from it. Both are published, both are in force, and for most goods they line up.

For fifteen CN codes we cannot get them to line up. Not "the data is unclear" — the route one act names for the good is not among the routes the other publishes a benchmark for. We have not found a reading of the two annexes that yields a figure.

We did not find this by reading. We found it by running every declarable combination through our own calculation and looking at what refused to resolve. What follows is that derivation, in full, so you can check it — and correct us if there is a reading we missed.

The letters, and what they actually mean

Both acts describe production routes with single letters in brackets. Most summaries treat these as if they were categories of goods. They are not. The Annex I legend encodes grade × route:

MarkerMeaning
(A) / (B)grey / white cement
(C) / (D) / (E)carbon steel via BF/BOF, DRI/EAF, Scrap/EAF
(F) / (G) / (H)the same three routes for low-alloy steel
(J)high-alloy steel (EAF)
(K) / (L)primary / secondary aluminium

Read the second axis carefully, because it is the one that causes the problem. BF/BOF is (C) for carbon steel and (F) for low-alloy steel. The letter does not tell you the furnace alone — it tells you the furnace and the grade.

And the grade is a composition fact. Implementing Regulation (EU) 2025/2620, point 5.2.3 draws the line at 8 % alloying elements. Your CN code does not carry that. Your customs declaration does not carry it. It lives in the mill certificate, if you have one.

Where the two do not meet

Take CN 7225 19 90 — flat-rolled products of other alloy steel, of silicon-electrical steel, other than grain-oriented, other than hot-rolled.

Implementing Regulation (EU) 2025/2621, the default-values annex, assigns it (F): low-alloy, BF/BOF route.

Implementing Regulation (EU) 2025/2620, the benchmark annex, publishes free-allocation benchmarks for that code as:

RouteBenchmark (tCO₂/t)
(C)1.488
(D)0.563
(E)0.138

There is no (F). The defaults act tells you which route to assume; the benchmark act publishes no value for that route. The two vocabularies do not meet.

This is not a rounding question. SEFA = CBAM_y × CSCF_y × BM_g needs a BM_g, and for this code under that marker the benchmark annex publishes none. If there is a reading of the two annexes that supplies one, we have not found it — and we would genuinely rather be told than keep blocking the good.

The neighbouring line makes it stranger: 7225 19 10, the hot-rolled sibling one row above, carries (C) — a route the benchmark table does publish. Same subheading, same annex, one code resolves and the next does not.

The fifteen codes

Eighteen (code, marker) pairs across fifteen distinct CN codes, all of them iron and steel — five under chapter 72, ten under chapter 73:

CN codeMarker named by the defaults act, unpublished in the benchmark act
7205 21 00(C), (E)
7225 19 90(F), (H)
7226 19 80(F), (H)
7228 30 41(F)
7228 30 49(F)
7304 31 20(F)
7304 31 80(F)
7304 51 10(C)
7304 51 81(C)
7304 51 89(C)
7304 59 82(C)
7304 59 83(C)
7304 59 89(C)
7306 50 21(C)
7306 50 80(C)

If you import any of these, this is worth checking against your own figures — not because your data is wrong, but because any figure you have been given for them rests on somebody having chosen a route. Ask which one, and on what basis.

How we know

We ran the full grid: 119 origins × 570 CN codes for import year 2026 — 67,830 combinations — through the same resolution chain our product uses in production, for a document that states no production route. That is the realistic case: a customs declaration does not tell you whether the steel came out of a blast furnace or an arc furnace.

OutcomeCount
Resolved to a figure66,820 (98.5 %)
Blocked — route not resolvable912
Blocked — more than one candidate default row98
Blocked — no default value at all0
Blocked — benchmark missing for a named route0

The two zero rows are guards on our own data load, not a verdict on the acts — read them that way and they would seem to say the contradiction does not exist. It does; it is caught by a different check, described below.

The last two lines are the ones that matter for trust in the data load. Zero missing default values means the annex is fully covered — no published benchmark is sitting there without a default value behind it. Zero missing benchmarks means the same in the other direction, for the combinations a real import produces.

The eighteen conflicts are caught one level up, by a separate check that walks every named marker in the annex rather than every import combination. That check does not tolerate a percentage: it asserts the exact list, so a nineteenth conflict — or the disappearance of one, should the Commission amend an annex — fails the build rather than passing quietly.

The other 912 are a different, milder shape: the annex marks a route for most origins of a code and leaves it unmarked for a few. CN 7207 19 12 is the pattern — (C) for 27 origins, (E) for 5, and nothing at all for North Macedonia, against a benchmark published per route (C 1.364 / D 0.475 / E 0.066). The act does not say which applies. Blocking is the honest answer.

What a calculator should do here

Refuse.

That is not evasion, it is the only defensible behaviour. There are three ways software can respond to a missing benchmark:

  1. Pick a route. Silently selects a different free allocation — for 7225 19 90 the published values range from 0.138 to 1.488, a factor of eleven. A wrong pick understates the obligation by an order of magnitude, and Article 26 penalises under-surrender at three to five times the certificate price.
  2. Treat the missing benchmark as zero. Maximises the obligation instead. Wrong in the safe direction, but still wrong, and it will not survive a verifier's question.
  3. Return no number, and say which code and which marker.

We do the third. Our calculation returns a typed blocked result carrying the reason, and writes no figures at all — because a missing input coerced to zero is a silent under-report, and a guessed route is a silent misstatement. The customer sees the CN code, the marker, and the sentence that this needs an answer from the Commission or from counsel.

What we deliberately do not do is quietly resolve to the lowest published benchmark, even though that would be the conservative direction. It would turn fifteen open legal questions into fifteen invented answers, and nobody looking at the output would know which was which.

The one thing you can do now

If your goods fall under any of the fifteen codes, ask your supplier for the mill certificate — specifically the alloying-element content. That is what decides carbon versus low-alloy, and it is the fact neither the CN code nor the customs declaration carries. With verified actual emissions the route question changes shape entirely, because you are no longer relying on the default table to tell you which furnace to assume.

It does not dissolve the contradiction. But it moves you from "the acts disagree about my goods" to "I can document what my goods actually are" — which is the position you want to be in when somebody asks.


This article explains the rules as we read them; it is not legal advice. The route markers and default values are set out in Implementing Regulation (EU) 2025/2621 and its Annex I legend, the free-allocation benchmarks and the grade definition in Implementing Regulation (EU) 2025/2620 (pt 5.2.3), and the penalty regime in Regulation (EU) 2023/956 as amended. The counts above are from our own reference-data census for import year 2026 and are pinned in our test suite; verify your own position with your customs agent or the competent authority in your member state — in Germany, the DEHSt.