{"record":{"id":"e5b473a4dd996f99","repo":"nopSolutions/nopCommerce","slug":"no-tier-price-found-with-the-specified-id","errorCode":null,"errorMessage":"No tier price found with the specified id","messagePattern":"No tier price found with the specified id","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Presentation/Nop.Web/Areas/Admin/Controllers/ProductController.cs","lineNumber":3171,"sourceCode":"            ViewBag.RefreshPage = true;\n\n            return View(model);\n        }\n\n        //prepare model\n        model = await _productModelFactory.PrepareTierPriceModelAsync(model, product, tierPrice, true);\n\n        //if we got this far, something failed, redisplay form\n        return View(model);\n    }\n\n    [HttpPost]\n    [CheckPermission(StandardPermission.Catalog.PRODUCTS_CREATE_EDIT_DELETE)]\n    public virtual async Task<IActionResult> TierPriceDelete(int id)\n    {\n        //try to get a tier price with the specified id\n        var tierPrice = await _productService.GetTierPriceByIdAsync(id)\n            ?? throw new ArgumentException(\"No tier price found with the specified id\");\n\n        //try to get a product with the specified id\n        var product = await _productService.GetProductByIdAsync(tierPrice.ProductId)\n            ?? throw new ArgumentException(\"No product found with the specified id\");\n\n        //a vendor should have access only to his products\n        var currentVendor = await _workContext.GetCurrentVendorAsync();\n        if (currentVendor != null && product.VendorId != currentVendor.Id)\n            return Content(\"This is not your product\");\n\n        await _productService.DeleteTierPriceAsync(tierPrice);\n\n        return new NullJsonResult();\n    }\n\n    #endregion\n\n    #region Product attributes","sourceCodeStart":3153,"sourceCodeEnd":3189,"githubUrl":"https://github.com/nopSolutions/nopCommerce/blob/64bdf2ff08c8b39e65717bcf974fb43dc2ef68f2/src/Presentation/Nop.Web/Areas/Admin/Controllers/ProductController.cs#L3153-L3189","documentation":"Thrown by the POST TierPriceDelete admin action when the tier price ID passed in does not resolve to any tier price row. The action calls _productService.GetTierPriceByIdAsync(id) and uses a null-coalescing throw to immediately raise an ArgumentException. Unlike the product-not-found errors, this fires on the primary entity lookup itself, not a parent reference.","triggerScenarios":"An AJAX delete call (POST /Admin/Product/TierPriceDelete?id=<id>) is issued for a tier price ID that does not exist — the row was already deleted, the ID was tampered, or the grid is stale.","commonSituations":"Double-click on a delete button where the first call succeeds and the second hits a now-missing row; browser back/forward replaying a stale AJAX request; a cron or script attempting to delete tier prices that were already removed; ID manipulation in a crafted POST.","solutions":["Check whether the tier price still exists before retrying — refresh the product's Tier Prices tab.","If you control the action, return a NullJsonResult or a 404 instead of throwing so the AJAX grid handles missing rows gracefully.","Ensure the frontend disables the delete button after the first click to prevent duplicate submissions.","Audit server logs for the exact id value to determine if the request is stale or malicious."],"exampleFix":"// before\nvar tierPrice = await _productService.GetTierPriceByIdAsync(id)\n    ?? throw new ArgumentException(\"No tier price found with the specified id\");\n\n// after\nvar tierPrice = await _productService.GetTierPriceByIdAsync(id);\nif (tierPrice == null)\n    return new NullJsonResult();","handlingStrategy":"validation","validationCode":"// Before calling delete, verify the tier price exists\nvar tierPrice = await _productService.GetTierPriceByIdAsync(id);\nif (tierPrice == null) return new NullJsonResult(); // already gone — treat as success","typeGuard":"public static bool TierPriceExists(int id, IProductService service) =>\n    service.GetTierPriceByIdAsync(id).GetAwaiter().GetResult() != null;","tryCatchPattern":"try\n{\n    return await _controller.TierPriceDelete(id);\n}\ncatch (ArgumentException ex) when (ex.Message.Contains(\"No tier price found\"))\n{\n    _logger.LogInformation(\"Tier price {Id} already deleted\", id);\n    return new NullJsonResult();\n}","preventionTips":["Disable the delete button immediately after the first click to prevent duplicate AJAX calls.","Return NullJsonResult instead of throwing for already-deleted entities in AJAX endpoints.","Log the requested ID to distinguish stale requests from malicious ones."],"tags":["nopcommerce","admin-controller","argument-exception","tier-price","delete-action","ajax"],"backgroundTag":null,"analyzedSha":"64bdf2ff08c8b39e65717bcf974fb43dc2ef68f2","analyzedAt":"2026-08-13T21:19:38.062Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}