nopSolutions/nopCommerce · error · ArgumentException
No product tag found with the specified id
Error message
No product tag found with the specified id
What it means
Thrown by ProductTagDelete when _productTagService.GetProductTagByIdAsync(id) returns null. Product tags are global catalog entities (no vendor ownership check here). The endpoint deletes a tag by id from the product-tags grid.
Source
Thrown at src/Presentation/Nop.Web/Areas/Admin/Controllers/ProductController.cs:2687
}
[HttpPost]
[CheckPermission(StandardPermission.Catalog.PRODUCT_TAGS_VIEW)]
public virtual async Task<IActionResult> ProductTags(ProductTagSearchModel searchModel)
{
//prepare model
var model = await _productModelFactory.PrepareProductTagListModelAsync(searchModel);
return Json(model);
}
[HttpPost]
[CheckPermission(StandardPermission.Catalog.PRODUCT_TAGS_CREATE_EDIT_DELETE)]
public virtual async Task<IActionResult> ProductTagDelete(int id)
{
//try to get a product tag with the specified id
var tag = await _productTagService.GetProductTagByIdAsync(id)
?? throw new ArgumentException("No product tag found with the specified id");
await _productTagService.DeleteProductTagAsync(tag);
_notificationService.SuccessNotification(await _localizationService.GetResourceAsync("Admin.Catalog.ProductTags.Deleted"));
return RedirectToAction("ProductTags");
}
[HttpPost]
[CheckPermission(StandardPermission.Catalog.PRODUCT_TAGS_CREATE_EDIT_DELETE)]
public virtual async Task<IActionResult> ProductTagsDelete(ICollection<int> selectedIds)
{
if (selectedIds == null || !selectedIds.Any())
return NoContent();
var tags = await _productTagService.GetProductTagsByIdsAsync(selectedIds.ToArray());
await _productTagService.DeleteProductTagsAsync(tags);
View on GitHub (pinned to 64bdf2ff08)
Solutions
- Make the delete idempotent: if the tag is gone, redirect to ProductTags without error.
- Refresh the tags grid after any delete or bulk delete.
- Disable the delete control until the AJAX response resolves.
- Replace the throw with a null guard returning a notification/redirect.
Example fix
// before
var tag = await _productTagService.GetProductTagByIdAsync(id)
?? throw new ArgumentException("No product tag found with the specified id");
await _productTagService.DeleteProductTagAsync(tag);
// after
var tag = await _productTagService.GetProductTagByIdAsync(id);
if (tag == null)
{
_notificationService.ErrorNotification(await _localizationService.GetResourceAsync("Admin.Catalog.ProductTags.NotExist"));
return RedirectToAction("ProductTags");
}
await _productTagService.DeleteProductTagAsync(tag); Defensive patterns
Strategy: validation
Validate before calling
var tag = await _productTagService.GetProductTagByIdAsync(id);
if (tag == null)
{
_notificationService.ErrorNotification("Tag no longer exists.");
return RedirectToAction("ProductTags");
} Try / catch
try { /* delete tag */ }
catch (ArgumentException ex) when (ex.Message.Contains("product tag"))
return RedirectToAction("ProductTags"); Prevention
- Make tag deletes idempotent
- Refresh tags grid after bulk delete
- Avoid double-click deletes
When it happens
Trigger: POST Admin/Product/ProductTagDelete?id=... for a tag already deleted (double delete), or a grid row stale after a prior delete or a ProductTagsDelete bulk action that already removed it.
Common situations: Double-click delete. Bulk ProductTagsDelete followed by an individual delete on the same id from a stale grid. Two admins managing tags concurrently.
Related errors
- No associated product found with the specified id
- No product picture found with the specified id
- No product video found with the specified id
- No picture found with the specified id
- No video found with the specified id
AI-assisted analysis of nopSolutions/nopCommerce@64bdf2ff08 (2026-08-13).
Data as JSON: /api/errors/c8b350c7cfa21377.
Report an issue: GitHub.