How can I limit the maximum weight of an order? Is there a way in drupal commerce 2 to prevent adding a product to the cart, if the order weight exceeds a certain amount, let's say 40kg?
We are also using the commerce_cart_api plugin, in case this provides some hooks to prevent an add?
Alright, I'm definetly not sure, if this is the intended way of doing things, but I did it now this way via a custom cart event subscriber:
modules/custom/my_checkout/my_checkout.services.yml:
services:
  my_checkout.cart_subscriber:
    class: Drupal\my_checkout\EventSubscriber\CartEventSubscriber
    arguments: ['@messenger', '@commerce_cart.cart_manager', '@string_translation']
    tags:
      - { name: event_subscriber }


modules/custom/my_checkout/src/EventSubscriber/CartEventSubscriber.php:
&lt;?php


namespace Drupal\my_checkout\EventSubscriber;

use Drupal\commerce_cart\CartManagerInterface;
use Drupal\commerce_cart\Event\CartEntityAddEvent;
use Drupal\commerce_cart\Event\CartEvents;
use Drupal\commerce_cart\Event\CartOrderItemRemoveEvent;
use Drupal\commerce_cart\Event\CartOrderItemUpdateEvent;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Core\TypedData\Exception\MissingDataException;
use Drupal\physical\Calculator;
use Drupal\physical\Weight;
use Drupal\physical\WeightUnit;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class CartEventSubscriber implements EventSubscriberInterface {

  use StringTranslationTrait;

  /**
   * The messenger.
   *
   * @var MessengerInterface
   */
  protected $messenger;

  /**
   * The cart manager.
   *
   * @var CartManagerInterface
   */
  protected $cartManager;

  /**
   * Constructs event subscriber.
   *
   * @param MessengerInterface $messenger
   *   The messenger.
   */
  public function __construct(MessengerInterface $messenger, CartManagerInterface $cart_manager, TranslationInterface $string_translation) {
    $this-&gt;messenger = $messenger;
    $this-&gt;cartManager = $cart_manager;
    $this-&gt;stringTranslation = $string_translation;
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    return [
      CartEvents::CART_ENTITY_ADD =&gt; [['guardWeight', 100]],
      CartEvents::CART_ORDER_ITEM_UPDATE =&gt; [['guardWeight', 100]],
      CartEvents::CART_ORDER_ITEM_REMOVE =&gt; [['guardWeight', 100]]
    ];
  }

  /**
   * @param CartEntityAddEvent|CartOrderItemUpdateEvent|CartOrderItemRemoveEvent $event
   * @throws MissingDataException
   */
  public function guardWeight($event) {
    $cart = $event-&gt;getCart();

    // @todo - this should be configurable
    $maximumWeight = new Weight(40, WeightUnit::KILOGRAM);
    $orderWeight = new Weight(0, WeightUnit::KILOGRAM);

    foreach ($cart-&gt;getItems() as $order_item) {

      $purchased_entity = $order_item-&gt;getPurchasedEntity();
      // Calculate only items with a weight
      if (!$purchased_entity || !$purchased_entity-&gt;hasField('weight')) {
        continue;
      }

      $quantity = $order_item-&gt;getQuantity();
      if (Calculator::compare($order_item-&gt;getQuantity(), '0') == 0) {
        continue;
      }

      /** @var Weight $weight */
      $weight = $purchased_entity-&gt;get('weight')-&gt;first()-&gt;toMeasurement();

      $orderWeight = $orderWeight-&gt;add($weight-&gt;multiply($quantity));
    }

    if (!$orderWeight-&gt;lessThanOrEqual($maximumWeight)) {

      switch (get_class($event)) {
        case CartOrderItemUpdateEvent::class:
          $orderItem = $event-&gt;getOrderItem();
          $originalQuantity = $event-&gt;getOriginalOrderItem()-&gt;getQuantity();
          if (intval($orderItem-&gt;getQuantity()) &gt; intval($originalQuantity)) {
            $orderItem-&gt;setQuantity($originalQuantity);
            $orderItem-&gt;save();
          }

          break;
        case CartEntityAddEvent::class:
          $orderItem = $event-&gt;getOrderItem();
          $cart-&gt;removeItem($orderItem);
          $orderItem-&gt;delete();
          break;
      }

      $this-&gt;messenger-&gt;addError($this-&gt;t('You would exceed the maximum order weight of @maxWeight, we could not update your cart.', [
        '@maxWeight' =&gt; implode('', $maximumWeight-&gt;toArray())
      ]));
    }
  }

}


It works well, but the &quot;Your cart was updated&quot; message is unfortunately still there. My guess is, it is still not the best location for this kind of logic.