{"record":{"id":"80b445c338973774","repo":"dotnet/eShop","slug":"discount-is-not-valid","errorCode":null,"errorMessage":"Discount is not valid","messagePattern":"Discount is not valid","errorType":"exception","errorClass":"OrderingDomainException","httpStatus":null,"severity":"error","filePath":"src/Ordering.Domain/AggregatesModel/OrderAggregate/OrderItem.cs","lineNumber":48,"sourceCode":"        if ((unitPrice * units) < discount)\n        {\n            throw new OrderingDomainException(\"The total of order item is lower than applied discount\");\n        }\n\n        ProductId = productId;\n\n        ProductName = productName;\n        UnitPrice = unitPrice;\n        Discount = discount;\n        Units = units;\n        PictureUrl = pictureUrl;\n    }\n    \n    public void SetNewDiscount(decimal discount)\n    {\n        if (discount < 0)\n        {\n            throw new OrderingDomainException(\"Discount is not valid\");\n        }\n\n        Discount = discount;\n    }\n\n    public void AddUnits(int units)\n    {\n        if (units < 0)\n        {\n            throw new OrderingDomainException(\"Invalid units\");\n        }\n\n        Units += units;\n    }\n}\n","sourceCodeStart":30,"sourceCodeEnd":64,"githubUrl":"https://github.com/dotnet/eShop/blob/9b4f9434f46fdc5c1a6e9e936af2868340cdbc48/src/Ordering.Domain/AggregatesModel/OrderAggregate/OrderItem.cs#L30-L64","documentation":"Thrown by OrderItem.SetNewDiscount when discount is less than zero. A negative discount is meaningless (it would raise the price), so the method rejects it as an invariant violation. It is an OrderingDomainException. Note this guard checks negativity only — a discount larger than the line total is not caught here.","triggerScenarios":"Calling existingOrderForProduct.SetNewDiscount(discount) (reached via Order.AddOrderItem when a higher discount is supplied for an existing line, or directly) with a negative discount value. Usually a sign-inversion or arithmetic bug computing the discount.","commonSituations":"A promo calculator returning a negative amount; subtraction producing a negative remainder; client sending a signed discount field; tests passing -1 as a sentinel.","solutions":["Validate discount >= 0 at the call site before invoking SetNewDiscount; reject negative values earlier.","Fix the upstream discount computation so it never yields a negative figure.","If a percentage model is used, compute absolute = subtotal * pct/100 which is inherently non-negative for non-negative inputs.","Add a guard in the command/handler: if (request.Discount < 0) return BadRequest(...)."],"exampleFix":"// before\nitem.SetNewDiscount(computedDiscount);\n\n// after\nif (computedDiscount < 0) throw new ArgumentException(\"Discount cannot be negative\");\nitem.SetNewDiscount(computedDiscount);","handlingStrategy":"validation","validationCode":"if (discount < 0) throw new ArgumentOutOfRangeException(nameof(discount));\nitem.SetNewDiscount(discount);","typeGuard":"static bool IsValidDiscount(decimal discount) => discount >= 0;","tryCatchPattern":"try {\n    item.SetNewDiscount(discount);\n} catch (OrderingDomainException ex) when (ex.Message == \"Discount is not valid\") {\n    // negative discount upstream — fix the promo calculation, do not retry as-is\n}","preventionTips":["Compute discounts from non-negative inputs (e.g. percentage model).","Guard discount >= 0 at the handler boundary.","Add unit tests covering discount == 0 and discount == subtotal."],"tags":["domain","ordering","validation","pricing","ddd"],"backgroundTag":null,"analyzedSha":"9b4f9434f46fdc5c1a6e9e936af2868340cdbc48","analyzedAt":"2026-08-13T19:29:36.594Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}