{"record":{"id":"f230aff394f61637","repo":"dotnet/eShop","slug":"item-units-desired-should-be-greater-than-zero","errorCode":null,"errorMessage":"Item units desired should be greater than zero","messagePattern":"Item units desired should be greater than zero","errorType":"validation","errorClass":"CatalogDomainException","httpStatus":null,"severity":"error","filePath":"src/Catalog.API/Model/CatalogItem.cs","lineNumber":71,"sourceCode":"    /// \n    /// If there is sufficient stock of an item, then the integer returned at the end of this call should be the same as quantityDesired. \n    /// In the event that there is not sufficient stock available, the method will remove whatever stock is available and return that quantity to the client.\n    /// In this case, it is the responsibility of the client to determine if the amount that is returned is the same as quantityDesired.\n    /// It is invalid to pass in a negative number. \n    /// </summary>\n    /// <param name=\"quantityDesired\"></param>\n    /// <returns>int: Returns the number actually removed from stock. </returns>\n    /// \n    public int RemoveStock(int quantityDesired)\n    {\n        if (AvailableStock == 0)\n        {\n            throw new CatalogDomainException($\"Empty stock, product item {Name} is sold out\");\n        }\n\n        if (quantityDesired <= 0)\n        {\n            throw new CatalogDomainException($\"Item units desired should be greater than zero\");\n        }\n\n        int removed = Math.Min(quantityDesired, this.AvailableStock);\n\n        this.AvailableStock -= removed;\n\n        return removed;\n    }\n\n    /// <summary>\n    /// Increments the quantity of a particular item in inventory.\n    /// <param name=\"quantity\"></param>\n    /// <returns>int: Returns the quantity that has been added to stock</returns>\n    /// </summary>\n    public int AddStock(int quantity)\n    {\n        int original = this.AvailableStock;\n","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/dotnet/eShop/blob/9b4f9434f46fdc5c1a6e9e936af2868340cdbc48/src/Catalog.API/Model/CatalogItem.cs#L53-L89","documentation":"Thrown by CatalogItem.RemoveStock when the supplied quantityDesired is less than or equal to zero. RemoveStock validates its input as a precondition because a non-positive decrement is a programming/contract error, not a legitimate inventory operation. It is a CatalogDomainException.","triggerScenarios":"A caller computes the desired quantity from a cart/order line and passes 0 or a negative value — e.g. an order item with Units <= 0, a default-int field that was never set, or arithmetic that underflowed. Also seen when an upstream mapping sends an empty/zero quantity.","commonSituations":"DTO mapping that drops an unset Quantity field to 0; client sending a request with no quantity; unit test invoking RemoveStock(0) as a no-op probe; subtraction producing a negative remainder passed straight through.","solutions":["Validate quantityDesired > 0 at the calling boundary (controller/handler) and reject the request with a 400 before it reaches the domain.","Trace where the quantity originates and ensure it is sourced from a positive Units value on the order line, never an unset default.","If the intent is to probe availability, read AvailableStock directly instead of calling RemoveStock with 0.","Add a guard clause / FluentValidation rule: RuleFor(x => x.Quantity).GreaterThan(0)."],"exampleFix":"// before\nvar taken = item.RemoveStock(line.Units); // line.Units may be 0\n\n// after\nif (line.Units <= 0) throw new ArgumentException(\"Quantity must be positive\", nameof(line.Units));\nvar taken = item.RemoveStock(line.Units);","handlingStrategy":"validation","validationCode":"if (qty <= 0) throw new ArgumentOutOfRangeException(nameof(qty));\nvar taken = item.RemoveStock(qty);","typeGuard":"static bool IsValidQuantity(int qty) => qty > 0;","tryCatchPattern":"try {\n    item.RemoveStock(qty);\n} catch (CatalogDomainException ex) when (ex.Message.Contains(\"greater than zero\")) {\n    // programming/contract error — log and reject the request as 400\n}","preventionTips":["Validate Quantity > 0 at the API boundary with FluentValidation.","Never forward an unset/default int quantity to the domain.","Probe availability by reading AvailableStock, not by calling RemoveStock(0)."],"tags":["domain","catalog-api","validation","precondition","inventory"],"backgroundTag":null,"analyzedSha":"9b4f9434f46fdc5c1a6e9e936af2868340cdbc48","analyzedAt":"2026-08-13T19:29:36.594Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}