Skip to content

Quote::updateItem() can create a duplicate configurable child item when the parent is re-added #41271

Description

@YasinCetin0

Preconditions and environment

  • Magento version: 2.4.8-p5
  • PHP 8.3

Steps to reproduce

  1. Add a configurable product to the cart.
  2. Trigger a second Quote::updateItem($parentItemId, $buyRequest) call for that
    same item — in our case this happened naturally via CartItemPersister::save()
    (triggered by a third-party module setting a custom price on a cart item, which
    causes Magento core to re-save/re-sync the quote a few seconds after the initial
    add), but any caller that invokes updateItem() a second time on an already
    fully-populated configurable item with a changed buyRequest can trigger it.
  3. Place the order.

Expected result

Exactly one parent + one child quote/order item for the configurable product.

Actual result

Two child items exist under the same parent, one of them with no price. Credit
memo creation later fails on that order with "invalid quantity to refund".

Additional information

Quote::updateItem() merges duplicate parent items after calling addProduct()
(see the if ($resultItem->getId() != $itemId) block), but it never checks for
duplicate child items. If addProduct()'s internal getItemByProduct() fails to
match an already-existing child against the freshly regenerated candidate — which
can happen when the parent's stored buyRequest/options differ slightly from the
state at initial add-to-cart — a second child quote item is created under the same
parent instead of the existing one being reused.

This results in an order with two child items for the same configurable product
(one legitimate, one with price/row_total = 0/NULL), and later breaks credit memo
creation with "We found an invalid quantity to refund item ...".

Release note

No response

Triage and priority

  • Severity: S0 - Affects critical data or functionality and leaves users without workaround.
  • Severity: S1 - Affects critical data or functionality and forces users to employ a workaround.
  • Severity: S2 - Affects non-critical data or functionality and forces users to employ a workaround.
  • Severity: S3 - Affects non-critical data or functionality and does not force users to employ a workaround.
  • Severity: S4 - Affects aesthetics, professional look and feel, “quality” or “usability”.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions