[Bug]: Whse. Jnl.-Register Line (Cod. 7301) forces Base UoM at non-directed bin-mandatory locations, making it impossible to correct multi-UoM Bin Content via Item Journal
@PredragMaricic is already working on this.
Since Aug 24, 2026.
- Dominant language
- AL
- Stars
- 683
- Forks
- 459
- Avg merge
- 3d 26m
- Merged PRs (30d)
- 633
Description
Describe the issue
At a warehouse location with Require Pick/Require Put-away = Yes and Directed Put-away and Pick = No
(a "non-directed" bin-mandatory location), Bin Content (table 7302) legitimately supports one row per
Location/Bin/Item/Variant/Unit of Measure Code — that combination is the table's primary key, and
Quantity (Base) is a per-row FlowField, not shared across UoM rows for the same bin.
Codeunit 7301 "Whse. Jnl.-Register Line" breaks this invariant in two related ways:
1. InitWhseEntry unconditionally forces the Base UoM for non-directed locations, discarding whatever
UoM the warehouse/item journal line was actually entered in — for both positive and negative movements:
end else begin
WhseEntry.Quantity := WhseJnlLine."Qty. (Absolute, Base)" * Sign;
WhseEntry."Unit of Measure Code" := WMSMgt.GetBaseUOM(WhseJnlLine."Item No.");
WhseEntry."Qty. per Unit of Measure" := 1;
end;
2. DeleteFromBinContent then looks up the Bin Content row to validate available quantity against,
using WhseEntry."Unit of Measure Code" — which, because of (1), is always the base UoM, never the
UoM the negative line was actually entered in:
FromBinContent.Get(
WhseEntry."Location Code", WhseEntry."Bin Code", WhseEntry."Item No.", WhseEntry."Variant Code",
WhseEntry."Unit of Measure Code");
Practical consequence: once an item has Bin Content rows in more than one UoM at the same bin
(which the system itself can create — see point 3 below), it becomes impossible to post a standard
correcting Item Journal entry (negative-adjustment-in-UoM-A / positive-adjustment-in-UoM-B) to
consolidate them: the negative line's availability check always resolves against the base-UoM row,
completely ignoring the non-base-UoM row's actual (sufficient) quantity.
3. Secondary instance of the same root inconsistency, on the insert/positive path, in the same
procedure — the existence check correctly uses the journal line's own entered UoM, but the actual row
write stamps the UoM from WhseEntry, which by this point has already been base-UoM-forced by (1):
if not ToBinContent.Get(
WhseJnlLine."Location Code", BinCode, WhseJnlLine."Item No.", WhseJnlLine."Variant Code",
WhseJnlLine."Unit of Measure Code") // <- entered UoM used for the check
then
InsertToBinContent(WhseEntry) // <- but WhseEntry."Unit of Measure Code" is base UoM
// InsertToBinContent
BinContent."Unit of Measure Code" := WhseEntry."Unit of Measure Code"; // always base UoM here
Different UoM source for the existence check vs. the actual write, inside the same if block.
Expected behavior
A negative adjustment entered in a non-base UoM, at a non-directed bin-mandatory location, should be
validated against — and consolidated with — the Bin Content row for that same UoM, not silently
redirected to the base-UoM row. Posting a correcting pair of Item Journal lines (negative in the
"wrong" UoM, positive in the intended UoM) at the same bin should succeed whenever the wrong-UoM row
actually holds enough quantity.
Steps to reproduce
- Create a Location with
Bin Mandatory= Yes (Require Pick/Require Put-away= Yes) and
Directed Put-away and Pick= No. - Create an Item with two Units of Measure, e.g.
EA(base) andPACK(Qty. per UoM = 1, to keep the
repro minimal — the defect does not require a real conversion factor). - Post a Positive Adjustment (Item Journal, or Warehouse Journal) of, say, 32
PACKinto a bin (e.g.
VIRTUAL) at that location. This creates aBin Contentrow keyed on
(Location, Bin, Item, Variant, UoM=PACK)withQuantity (Base) = 32(assuming 1:1 conversion). - Attempt to post a correcting Item Journal batch consisting of:
- a negative adjustment of
32 EA(the base UoM) at the same bin, and - a positive adjustment of
32 PACKat the same bin (net-zero, intended to reclassify/consolidate).
- a negative adjustment of
- Preview-post (or post) the negative
EAline.
Additional behavior observed / error text
Reproduced live via Preview Posting on a production BC 27.5 environment (build 27.5.46862.52525):
Quantity (Base) is not sufficient to complete this action. The quantity in the bin is 0.
32 units are not available in Bin Content Location Code='WH2',Bin Code='VIRTUAL',Item No.='KBBB',
Variant Code='',Unit of Measure Code='EA'.
— even though the same bin's PACK-UoM Bin Content row has the full 32 units available. The negative
line is validated against the (non-existent / empty) base-UoM Bin Content row instead of the actual
PACK-UoM row that holds the quantity, because DeleteFromBinContent always looks up by base UoM at
non-directed locations, regardless of which UoM the line was entered in.
Source references
Original review — StefanMaron/MSDyn365BC.Sandbox.Code.History, branch w1-27.5,
WhseJnlRegisterLine.Codeunit.al:
InitWhseEntrybase-UoM-forcing block: ~lines 143–151DeleteFromBinContentmismatched lookup: ~lines 217–220- Insert-path check/write mismatch: check ~line 184, write via
InsertToBinContent~line 424
Current review — microsoft/bcapps, branch main (targeting app version 29.0.0.0), commit
096090d6f8f05d59fb490426f89cd51537d01d3c (2026-07-22),
src/Layers/W1/BaseApp/Warehouse/Journal/WhseJnlRegisterLine.Codeunit.al:
InitWhseEntrybase-UoM-forcing block: lines 145–153DeleteFromBinContentmismatched lookup: lines 219–222- Insert-path check/write mismatch: check lines 186–188, write via
InsertToBinContentline 426
The logic is unchanged between these two checkpoints (spanning roughly BC 27.5 through the 29.0
development branch), so this affects every version in between as well as whatever is currently
supported in production. Note: the Base Application source only became visible in this public
bcapps repository on main via commit 748fdaa (2026-06-29, "Sync from BCAppsPrivate + NAV") — no
released version's Base App source (28.3 and earlier) is public here to diff against directly, but the
carried-forward logic strongly indicates the defect is present unmodified in all supported releases.
Suggested fix direction
Either (or both):
DeleteFromBinContentshould not blindly trustWhseEntry."Unit of Measure Code"(which is
base-UoM-forced for non-directed locations). Before theFromBinContent.Get(...)call, it should
check whether aBin Contentrow exists for the entered line UoM at that bin with sufficient
Quantity (Base), and prefer that row over the base-UoM row when it does.InitWhseEntryshould not silently discard the entered UoM for non-directed locations in the
first place when a non-base-UoMBin Contentrow already exists for that Location/Bin/Item/Variant —
at minimum, the existence check and the eventual write (in the insert path) should be consistent
with each other, which they currently are not (see point 3 above).
- I will provide a fix for a bug
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.