nopSolutions/nopCommerce · error · ArgumentException

No cross-sell product found with the specified id

Error message

No cross-sell product found with the specified id

What it means

Thrown by the CrossSellProductDelete action when _productService.GetCrossSellProductByIdAsync(id) returns null (?? throw new ArgumentException). This AJAX delete handler removes a cross-sell product mapping. The uncaught ArgumentException surfaces as an HTTP 500 to the grid delete request.

Source

Thrown at src/Presentation/Nop.Web/Areas/Admin/Controllers/ProductController.cs:1822

        //a vendor should have access only to his products
        var currentVendor = await _workContext.GetCurrentVendorAsync();
        if (currentVendor != null && product.VendorId != currentVendor.Id)
            return Content("This is not your product");

        //prepare model
        var model = await _productModelFactory.PrepareCrossSellProductListModelAsync(searchModel, product);

        return Json(model);
    }

    [HttpPost]
    [CheckPermission(StandardPermission.Catalog.PRODUCTS_CREATE_EDIT_DELETE)]
    public virtual async Task<IActionResult> CrossSellProductDelete(int id)
    {
        //try to get a cross-sell product with the specified id
        var crossSellProduct = await _productService.GetCrossSellProductByIdAsync(id)
            ?? throw new ArgumentException("No cross-sell product found with the specified id");

        //a vendor should have access only to his products
        var currentVendor = await _workContext.GetCurrentVendorAsync();
        if (currentVendor != null)
        {
            var product = await _productService.GetProductByIdAsync(crossSellProduct.ProductId1);
            if (product != null && product.VendorId != currentVendor.Id)
                return Content("This is not your product");
        }

        await _productService.DeleteCrossSellProductAsync(crossSellProduct);

        return new NullJsonResult();
    }

    [CheckPermission(StandardPermission.Catalog.PRODUCTS_CREATE_EDIT_DELETE)]
    public virtual async Task<IActionResult> CrossSellProductAddPopup(int productId)
    {

View on GitHub (pinned to 64bdf2ff08)

Solutions

  1. Reload the grid — the mapping is already removed; treat as success.
  2. Make delete idempotent by returning NullJsonResult when the mapping is null.
  3. Disable the delete control client-side after the first click.
  4. In automation, tolerate 'already deleted' instead of erroring.

Example fix

// before
var crossSellProduct = await _productService.GetCrossSellProductByIdAsync(id)
    ?? throw new ArgumentException("No cross-sell product found with the specified id");

// after — idempotent delete
var crossSellProduct = await _productService.GetCrossSellProductByIdAsync(id);
if (crossSellProduct == null)
    return new NullJsonResult();
Defensive patterns

Strategy: validation

Validate before calling

// Idempotent delete: tolerate already-removed cross-sell mappings
var crossSellProduct = await _productService.GetCrossSellProductByIdAsync(id);
if (crossSellProduct == null)
    return new NullJsonResult(); // already deleted

Type guard

if (id <= 0) return BadRequest("Invalid cross-sell product id");

Try / catch

try { var csp = await _productService.GetCrossSellProductByIdAsync(id); if (csp == null) return new NullJsonResult(); await _productService.DeleteCrossSellProductAsync(csp); ... } catch (ArgumentException) { return new NullJsonResult(); }

Prevention

When it happens

Trigger: POST to delete a cross-sell mapping by id that no longer exists — already deleted, duplicate delete, or stale grid row.

Common situations: Double-click on delete; concurrent admins deleting the same mapping; scripted bulk delete revisiting an id; a grid not refreshed after a prior delete.

Related errors


AI-assisted analysis of nopSolutions/nopCommerce@64bdf2ff08 (2026-08-13). Data as JSON: /api/errors/b882d1867c763f08. Report an issue: GitHub.