Critical Magento 2 Tax Bug: Double Shipping Tax on Invoices and Credit Memos
Unpacking a Critical Magento 2 Tax Glitch: Double Shipping Tax on Invoices and Credit Memos
As e-commerce migration experts at Shopping Mover, we constantly monitor the Magento ecosystem for critical insights that can impact merchants and developers. A recent GitHub issue (#41031) has brought to light a significant tax calculation bug in Magento Open Source 2.4.9 (and potentially 2.4-develop) that could lead to incorrect financial reporting and over-refunds.
The Core Problem: Shipping Tax Duplication
The issue arises when Magento is configured to calculate shipping prices "Including Tax". Under these specific conditions, the system incorrectly persists the shipping_amount as a tax-inclusive value, even though the shipping_tax_amount is stored separately. This fundamental inconsistency leads to a critical flaw: when an invoice is generated, the shipping tax is effectively added twice, inflating the invoice's grand total.
Consider an example where a shipping method costs €4.95 (including 19% VAT). The expected breakdown should be:
shipping_amount = 4.16
shipping_tax_amount = 0.79
shipping_incl_tax = 4.95
However, the bug causes Magento to persist:
shipping_amount = 4.95
shipping_tax_amount = 0.79
shipping_incl_tax = 4.95
While the order grand total might appear correct initially due to internal quote aggregation, the invoice creation process adds both the incorrectly tax-inclusive shipping_amount and the separate shipping_tax_amount, resulting in an invoice grand total that is higher by exactly the shipping tax amount (e.g., €11.69 instead of €10.90).
Expanded Impact: Over-Refunds on Credit Memos
Further investigation by the issue author, simonmaass, confirmed that this malformed shipping data tuple also impacts credit memo generation. For affected orders, creating a full credit memo can lead to over-refunds, again by the exact shipping tax amount. This occurs because the credit memo total collectors also add shipping_amount (as if it were tax-exclusive) and then separately add shipping_tax_amount, duplicating the tax.
Deep Dive: The Technical Root Cause
The heart of the problem lies within Magento's tax calculation logic, specifically in the Magento\Tax\Model\Sales\Total\Quote\CommonTaxCollector::processShippingTaxInfo() method. While this method correctly recalculates the tax-exclusive shipping row total and updates internal total amounts, it fails to update the ordinary shipping_amount and base_shipping_amount data properties. Consequently, when the quote totals collector later copies data back to the quote address, these stale, tax-inclusive values overwrite the correct tax-exclusive amounts.
The proposed fix is a small but crucial synchronization within CommonTaxCollector::processShippingTaxInfo():
$total->setTotalAmount('shipping', $shippingTaxDetails->getRowTotal());
$total->setBaseTotalAmount('shipping', $baseShippingTaxDetails->getRowTotal());
+$total->setShippingAmount($shippingTaxDetails->getRowTotal());
+$total->setBaseShippingAmount($baseShippingTaxDetails->getRowTotal());
This ensures that the shipping_amount properties accurately reflect the tax-exclusive value, preventing the subsequent double-counting.
Community Interaction and Implications
The issue was reported with a critical S0 severity, indicating it affects critical data and functionality without a workaround. Interestingly, the Magento engineering team initially struggled to reproduce the issue on the latest 2.4-develop branch. This highlights the importance of meticulously following all preconditions, especially ensuring a tax rule is specifically applied to shipping and that shipping prices are configured as "Including Tax."
For Magento merchants, this bug can lead to significant financial discrepancies, impacting accounting, reporting, and customer trust due to incorrect invoice totals and over-refunds. Developers should be aware of this specific issue, especially when working with tax configurations, custom shipping methods, or migrating data. While the proposed fix addresses new orders, existing malformed orders would require data repair or defensive handling during invoice/credit memo creation.
Monitoring the GitHub issue for official patches or community-contributed solutions is highly recommended for anyone affected by this critical tax calculation anomaly.