{"record":{"id":"06b24e4efd1f1735","repo":"dotnet/eShop","slug":"is-not-possible-to-change-the-order-status-from-o","errorCode":null,"errorMessage":"Is not possible to change the order status from {OrderStatus} to {orderStatusToChange}.","messagePattern":"Is not possible to change the order status from (.+?) to (.+?)\\.","errorType":"exception","errorClass":"OrderingDomainException","httpStatus":null,"severity":"error","filePath":"src/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs","lineNumber":182,"sourceCode":"\n            var itemsStockRejectedDescription = string.Join(\", \", itemsStockRejectedProductNames);\n            Description = $\"The product items don't have stock: ({itemsStockRejectedDescription}).\";\n        }\n    }\n\n    private void AddOrderStartedDomainEvent(string userId, string userName, int cardTypeId, string cardNumber,\n            string cardSecurityNumber, string cardHolderName, DateTime cardExpiration)\n    {\n        var orderStartedDomainEvent = new OrderStartedDomainEvent(this, userId, userName, cardTypeId,\n                                                                    cardNumber, cardSecurityNumber,\n                                                                    cardHolderName, cardExpiration);\n\n        this.AddDomainEvent(orderStartedDomainEvent);\n    }\n\n    private void StatusChangeException(OrderStatus orderStatusToChange)\n    {\n        throw new OrderingDomainException($\"Is not possible to change the order status from {OrderStatus} to {orderStatusToChange}.\");\n    }\n\n    public decimal GetTotal() => _orderItems.Sum(o => o.Units * o.UnitPrice);\n}\n","sourceCodeStart":164,"sourceCodeEnd":187,"githubUrl":"https://github.com/dotnet/eShop/blob/9b4f9434f46fdc5c1a6e9e936af2868340cdbc48/src/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs#L164-L187","documentation":"Thrown by Order.StatusChangeException, invoked from SetShippedStatus (when the current status is not Paid) and SetCancelledStatus (when the current status is Paid or Shipped). It guards the order state machine: only defined transitions are allowed (e.g. Paid -> Shipped, AwaitingValidation -> Cancelled). An OrderingDomainException signals an illegal state transition was requested.","triggerScenarios":"Calling order.SetShippedStatus() while OrderStatus is anything other than Paid (Submitted/AwaitingValidation/StockConfirmed/Cancelled). Calling order.SetCancelledStatus() on an order that is already Paid or Shipped. Triggered by out-of-order command processing, replayed commands, or UI/staff actions that assume a later state than the aggregate is actually in.","commonSituations":"Duplicate or reordered domain commands (e.g. shipping command arriving before the paid event was applied); a saga/orchestrator firing the ship step without confirming payment succeeded; manual admin tool issuing Cancel on an already-paid order; integration tests not resetting order state between steps.","solutions":["Before invoking SetShippedStatus, confirm OrderStatus == OrderStatus.Paid; before SetCancelledStatus, confirm it is not Paid or Shipped — branch or reject otherwise.","Make command handlers idempotent and ordered: ensure the SetPaidStatus event has been applied before a ship command is dispatched (use a saga with a wait-on-payment step).","On an illegal-transition OrderingDomainException, re-read the aggregate and either no-op if already in the target state or surface a conflict to the caller rather than retrying unchanged.","Add optimistic concurrency so a stale aggregate version cannot apply a transition against an outdated OrderStatus."],"exampleFix":"// before\norder.SetShippedStatus();\n\n// after\nif (order.OrderStatus != OrderStatus.Paid) {\n    throw new InvalidOperationException($\"Cannot ship: order is {order.OrderStatus}\");\n}\norder.SetShippedStatus();","handlingStrategy":"validation","validationCode":"if (order.OrderStatus != OrderStatus.Paid) return Error($\"Cannot ship from {order.OrderStatus}\");\norder.SetShippedStatus();","typeGuard":"static bool CanShip(Order o) => o.OrderStatus == OrderStatus.Paid;\nstatic bool CanCancel(Order o) => o.OrderStatus != OrderStatus.Paid && o.OrderStatus != OrderStatus.Shipped;","tryCatchPattern":"try {\n    order.SetShippedStatus();\n} catch (OrderingDomainException ex) when (ex.Message.Contains(\"Is not possible to change\")) {\n    // re-read aggregate; no-op if already in target state, else report conflict\n}","preventionTips":["Order domain commands so payment is applied before shipping.","Make command handlers idempotent.","Use optimistic concurrency to avoid transitions against a stale OrderStatus."],"tags":["domain","ordering","state-machine","ddd","concurrency"],"backgroundTag":null,"analyzedSha":"9b4f9434f46fdc5c1a6e9e936af2868340cdbc48","analyzedAt":"2026-08-13T19:29:36.594Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}