UOM Mismatch Issue Between like Purchase PO and Receipt

In the Purchase Order, I request items using the Kilogram (Kg) unit.
However, during Purchase Receipt, I receive the items using different units such as Piece or Carton.

I have already set up the UOM Conversion inside the Item, so that Piece and Carton convert correctly to Kilogram.
But when I try to submit the Purchase Receipt with a different UOM, I get the following error:

**Incorrect value in row 1: UOM must be equal to ‘Kg’
**

Hi @magedbjn,

This error is ERPNext’s “stock cycle UOM” guard kicking in. When a Purchase Receipt is created against a Purchase Order, ERPNext enforces that the UOM in the receipt row matches the UOM that was used in the PO row — irrespective of what conversions you’ve set up on the Item master. The UOM Conversion table on the Item only affects the conversion factor; it doesn’t permit cross-UOM receiving by itself. So even though your conversions are correctly defined, the validator at submission time is comparing the row-level UOMs and failing before the conversion factor ever gets applied.

The cleanest way to handle this — without losing the link to the original Purchase Order — is a small customization on the Purchase Receipt Item:

Step 1 — Add a Custom Field on Purchase Receipt Item

Create two custom fields on the Purchase Receipt Item doctype:

  • custom_received_qty (Float) — “Received Qty (in receiving UOM)”

  • custom_received_uom (Link to UOM) — “Receiving UOM (Piece / Carton)”

The user will enter the actual quantity received in Piece or Carton in these fields. The standard qty / uom columns will continue to hold the Kg figure that matches the PO row.

Step 2 — Client Script on Purchase Receipt

Add a Client Script (DocType: Purchase Receipt, Apply To: Form) that watches custom_received_qty and custom_received_uom, pulls the right conversion factor from the Item’s UOM Conversion table, and writes the converted Kg value into qty — plus recalculates the per-Kg rate from the per-Carton rate:

frappe.ui.form.on('Purchase Receipt Item', {
    custom_received_qty: function(frm, cdt, cdn) {
        recalc_from_receiving_uom(frm, cdt, cdn);
    },
    custom_received_uom: function(frm, cdt, cdn) {
        recalc_from_receiving_uom(frm, cdt, cdn);
    }
});

function recalc_from_receiving_uom(frm, cdt, cdn) {
    const row = locals[cdt][cdn];
    if (!row.item_code || !row.custom_received_uom || !row.custom_received_qty) return;

    frappe.db.get_value(
        'UOM Conversion Detail',
        { parent: row.item_code, uom: row.custom_received_uom },
        'conversion_factor'
    ).then(r => {
        const cf = r.message && r.message.conversion_factor;
        if (!cf) {
            frappe.msgprint(__('No UOM conversion found for {0} → stock UOM on item {1}',
                [row.custom_received_uom, row.item_code]));
            return;
        }

        // Convert receiving qty (e.g. Cartons) to stock/PO UOM (Kg)
        const stock_qty = flt(row.custom_received_qty) * flt(cf);
        frappe.model.set_value(cdt, cdn, 'qty', stock_qty);

        // Adjust rate: if user typed a per-Carton rate elsewhere, divide it down to per-Kg.
        // Here we assume row.rate is currently per-receiving-UOM; convert to per-stock-UOM.
        if (row.rate) {
            const rate_per_stock_uom = flt(row.rate) / flt(cf);
            frappe.model.set_value(cdt, cdn, 'rate', rate_per_stock_uom);
        }
    });
}

Why this is the right shape:

  • The PO row stays in Kg and the PR row’s uom/qty also stays in Kg, so the UOM equality check passes and the PO → PR linkage (with its over-receipt tolerance, billed-qty tracking, etc.) is preserved.

  • The user enters what they physically count — Cartons or Pieces — into the custom fields, and the script silently converts to Kg in the background using the conversion factor already defined on the Item.

  • The rate also gets adjusted, so if your supplier quotes per-Carton, the GL hits the correct per-Kg rate without manual math.

Two small notes:

  1. If rate on your Purchase Receipt is being fetched from the PO (already per-Kg), remove the rate-adjustment block from the script — otherwise it’ll double-divide.

  2. For audit clarity, you can show the receiving UOM and qty on the print format so the warehouse team sees what they actually counted, while accounting/stock continues to work in Kg.

Hope this helps! If you’d like, share a screenshot of the Item’s UOM Conversion table and I can tighten the script around your specific UOMs.

In ERPNext, the UOM used in the Purchase Receipt must match the UOM defined in the linked Purchase Order item.

In this case, the Purchase Order was created using the UOM “Kg”, but during Purchase Receipt the item is being received using another UOM such as “Piece” or “Carton”.

Although the UOM conversion is already configured correctly in the Item master, ERPNext still validates the transaction UOM against the original Purchase Order row. Because of this, the system shows the following error:

“Incorrect value in row 1: UOM must be equal to ‘Kg’”

The current UOM conversion setup is correct. For example:

  • Kg = 1

  • Piece = 17

This means ERPNext correctly understands that 1 Piece equals 17 Kg. However, the conversion factor is only used for stock quantity calculation and internal conversion. It does not allow changing the UOM between linked documents.

The recommended ERPNext workflow is:

  • Keep the Stock UOM as “Kg”

  • Add additional UOMs like Piece or Carton with proper conversion factors

  • Create the Purchase Order itself using the same UOM in which the vendor supplies the item

Example:

Purchase Order → Piece
Purchase Receipt → Piece
Stock maintained internally → Kg

ERPNext will automatically convert the received quantity into Kg for stock valuation and inventory calculations.

The issue occurs because the Purchase Order was created in “Kg” while the Purchase Receipt is being created in a different UOM. In linked transactions, ERPNext expects both documents to use the same transaction UOM.