I have an menu option to create multiple shipments from selected orders in an extension.

It works on some stores (tested) but the store I'm trying to get it to work on (2.3.1) uses MSI and I'm wondering if it's something to do with that?

 protected function massAction(AbstractCollection $collection)

        $countShipOrder = 0;
        foreach ($collection->getItems() as $order) 
                $shipOrder = $this->_shipOrder->create();
                $ship = $shipOrder->shipOrder($order->getId());
            catch (\Exception $e) 
                $this->messageManager->addError(__('Order Shipments Already Created For : %1',$order['increment_id']));

        $countNonShipOrder = $collection->count() - $countShipOrder;

        if ($countShipOrder) {

            $string = $countShipOrder.' success, '.$countNonShipOrder .' fails';
            $this->messageManager->addSuccess(__('Order shipments processed : %1.', $string));



class ShipOrder extends \Magento\Framework\Model\AbstractModel
    protected $_scopeConfig;
    protected $_order;
    protected $_orderConverter;
    protected $eventManager;

    public function __construct(
           \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
           \Magento\Sales\Model\OrderFactory $order,
           \Magento\Sales\Model\Convert\OrderFactory $orderConverter,
           \Magento\Framework\Event\Manager $eventManager,
           \Magento\Framework\Model\Context $context

        $this->_scopeConfig = $scopeConfig;
        $this->_order = $order;
        $this->eventManager = $eventManager;
        $this->_orderConverter = $orderConverter;

    public function shipOrder($orderId)
        //load by order 
        $order = $this->_order->create()->load($orderId);

        // Check if order can be shipped or has already shipped
        if ( !$order->canShip()) {
            throw new \Magento\Framework\Exception\LocalizedException(
                            __('You can\'t create an shipment for order increment id: %1', $order->getIncrementId())
            return false;
        else {
            $shipment = $this->createShipment($order);
            return  $shipment;

    public function createShipment($order){

        // Initialize the order shipment object
        $convertOrder = $this->_orderConverter->create();
        $shipment = $convertOrder->toShipment($order);

        // Loop through order items
        foreach ($order->getAllItems() as $orderItem) {
            // Check if order item has qty to ship or is virtual
            if (! $orderItem->getQtyToShip() || $orderItem->getIsVirtual()) {

            $qtyShipped = $orderItem->getQtyToShip();

            // Create shipment item with qty
            $shipmentItem = $convertOrder->itemToShipmentItem($orderItem)->setQty($qtyShipped);
            // Add shipment item to shipment
        // Register shipment
        try {
            // Save created shipment and order
            return $shipment;

        } catch (\Exception $e) {
            throw new \Magento\Framework\Exception\LocalizedException(__($e->getMessage()));

That final try catch where it tries to save the shipment is where the error is being thrown.

The undefined variable sourceCode is coming from /vendor/magento/module-inventory-shipping/Observer/SourceDeductionProcessor.php on line 112

  • Have you search for sourceCode references? – André Ferraz Aug 7 at 10:37
  • I missed the full exception, my bad, I've put in where the undefined variable sits in Magento vendor – Mark Aug 7 at 10:44
  • Well I'm afraid you going to have to put a fix of your own github.com/magento/inventory/blob/2.3-develop/app/code/Magento/… Is not done properly :/ – André Ferraz Aug 7 at 10:55
  • this doesnt help explain to me what the problem is. – Mark Aug 7 at 13:34
  • The problem is $this->isSingleSourceMode->execute() and $shipment->getExtensionAttributes() fail the conditions therefore the $sourceCode variable is never initialise. You will need to find out why both of those fail. Use a debugger and trace it down. – André Ferraz Aug 7 at 13:42

As MSI has been implemented, in your code you have to specify the source location.

Add the following line before $shipment save()


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.