When applying a fixed amount off promotion (order subtotal discount) with a coupon, the following error occurs:

Error: Call to a member function split() on null in Drupal\commerce_promotion\Plugin\Commerce\PromotionOffer\OrderFixedAmountOff->apply() (line 58 of
/app/web/modules/contrib/commerce/modules/promotion/src/Plugin/Commerce/PromotionOffer/OrderFixedAmountOff.php)

The root cause is in commerce_currency_resolver_exchanger module's OrderFixedAmountOff class (modules/exchanger/src/Plugin/Commerce/PromotionOffer/OrderFixedAmountOff.php). This class extends the
base Commerce OrderFixedAmountOff and overrides the create() method to inject additional currency resolver services, but fails to inject the $splitter property that the parent class requires.

When the parent's apply() method executes, it attempts to call $this->splitter->split($order, $amount) at line 58, but $splitter is null, resulting in a fatal error

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

c_archer created an issue. See original summary.

c_archer’s picture

Status: Active » Needs review

introfini made their first commit to this issue’s fork.

introfini’s picture

Improved fix in MR !13

Thanks @c_archer for identifying the root cause and providing the initial patch — it pointed straight to the problem!

I've pushed an alternative fix to MR !13 that goes a step further. The original patch adds $instance->splitter which fixes the immediate crash, but the new static() pattern still bypasses the rest of
the parent create() chain, leaving two other things uninitialized:

  • $this->rounder (from PromotionOfferBase::create())
  • setConfiguration() is never called, so defaultConfiguration() values are not merged with stored config

The sibling class OrderItemFixedAmountOff in the same module already follows the correct pattern — calling parent::create() and then adding its own services. MR !13 applies the same approach to
OrderFixedAmountOff:

  • Removed the constructor that forced new static()
  • Declared properties explicitly (consistent with OrderItemFixedAmountOff)
  • Replaced new static() with parent::create() so the full chain runs: PromotionOfferBase::create() (sets rounder, calls setConfiguration) → OrderPromotionOfferBase::create()
    (sets splitter) → our override (sets currency resolver services)

This also future-proofs against any new services added to the parent chain in Commerce core.

Verified both splitter and rounder are properly initialized after the fix.

valic made their first commit to this issue’s fork.

  • valic committed a55737f2 on 2.x authored by introfini
    Issue #3568323: Fix OrderFixedAmountOff create() to use parent::create()
    
valic’s picture

Status: Needs review » Reviewed & tested by the community

tnx to all, updated, add tests, did clean up all of the conditions

valic’s picture

Status: Reviewed & tested by the community » Fixed

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

  • valic committed a55737f2 on 2.0.x authored by introfini
    Issue #3568323: Fix OrderFixedAmountOff create() to use parent::create()
    

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.