Odoo upgrade error

UoM category should only have one reference unit of measure

Last updated: October 2026

Two units in the same category are marked as the reference unit. Odoo tolerates it until something writes a unit in that category, which an upgrade does.

This page is part of our guide on how to upgrade Odoo Community Edition. It explains what triggers the error, how to fix it by hand, and what an automated migration does about it.

The error

odoo.exceptions.ValidationError: UoM category Surface should only have one reference unit of measure.

The category name differs per database. The check exists in Odoo 15 to 18; Odoo 19 replaced UoM categories with a tree of units.

Raised by
uom.uom constraint on category_id / uom_type (Odoo 15 to 18)
Upgrade hops
15→16, 16→17, 17→18; we have traced it on 16→17
Seen when
A module writes units of measure while loading its data

When you see it

Each UoM category must have exactly one unit of type Reference. The constraint only runs when a unit in the category is created or written, and it counts archived units too. A database can hold two reference units in a category for years. During an upgrade, any module whose data file writes a unit of that category triggers the check. In the case we traced, a Spanish e-invoicing module that was installed automatically during the upgrade wrote its units and hit the Surface category.

Root cause

Typically a user created their own unit, for example cm2, as the reference of a category whose standard reference (m²) was archived. Because the archived unit still counts, the category now has two. List the categories with more than one reference unit:

SELECT u.category_id, u.id, u.name, u.active, u.factor
FROM uom_uom u
WHERE u.uom_type = 'reference'
  AND u.category_id IN (
    SELECT category_id FROM uom_uom
    WHERE uom_type = 'reference'
    GROUP BY category_id
    HAVING count(*) > 1)
ORDER BY u.category_id, u.id;

How to fix it

Keep one reference unit per category, normally the standard one that has an Odoo external ID (for example uom.uom_square_meter). Change the other to Smaller or Bigger and give it the right ratio. In Odoo, the factor of a smaller unit says how many of it make one reference unit: 1 m² is 10,000 cm², so cm² gets factor 10000.

Before you change anything: Back up the database before running any UPDATE or INSERT below, and try it on a copy first. These statements change data directly, outside the Odoo ORM.

-- example: unit 27 (cm2) becomes a smaller unit of the Surface category
UPDATE uom_uom
SET uom_type = 'smaller', factor = 10000
WHERE id = 27;

If documents already use the demoted unit, a new factor changes how their quantities convert to the reference unit. Check stock and sales documents in that unit on a copy before you apply it to production. If the archived standard unit should be the one in use, reactivate it.

How OCU handles it

Every OCU hop runs a repair in the base pre-migration script: for each category with more than one reference unit, it keeps the unit owned by a standard module external ID, or the oldest one if none is, and switches the others to Smaller or Bigger while keeping their factor unchanged. Only the type flag moves, so no quantity converts differently than before the upgrade.

Because the factor is kept, a demoted unit that had factor 1 still converts one to one with the reference. If that is not the real ratio, correct the factor after the migration.

A free test migration shows whether your database runs into this or any other upgrade error before you change anything on your production server.

Frequently asked questions

Why does Odoo count archived units?
The constraint reads the units with active_test disabled, so an archived reference unit still counts as the category reference. Reactivating or demoting it is the only way to satisfy the check.
Does Odoo 19 still have this error?
No. Odoo 19 removed UoM categories; units now point at a reference unit through a relative factor. The error can still stop an upgrade on any hop up to Odoo 18 when the source data has two reference units in one category.

Related

Find upgrade errors before your production run

Upload a backup and run a free test migration. You get the upgraded database, the full log and every warning, with no change to your live system.

Start your free test migration