nopSolutions/nopCommerce · error · ArgumentException
No specification attribute found with the specified id
Error message
No specification attribute found with the specified id
What it means
Thrown in PrepareAddSpecificationAttributeModelAsync when editing an existing product specification attribute. The factory loads the attribute by specificationId via GetProductSpecificationAttributeByIdAsync; if null (the id does not match any ProductSpecificationAttribute row) it throws ArgumentException. This typically means the requested specification id was deleted, the URL/query id is stale, or the value was never persisted.
Source
Thrown at src/Presentation/Nop.Web/Areas/Admin/Factories/ProductModelFactory.cs:1733
{
if (!specificationId.HasValue)
{
return new AddSpecificationAttributeModel
{
AvailableAttributes = await (await _specificationAttributeService.GetSpecificationAttributesWithOptionsAsync())
.SelectAwait(async attributeWithOption =>
{
var attributeName = await GetSpecificationAttributeNameAsync(attributeWithOption);
return new SelectListItem(attributeName, attributeWithOption.Id.ToString());
}).ToListAsync(),
ProductId = productId,
Locales = await _localizedModelFactory.PrepareLocalizedModelsAsync<AddSpecificationAttributeLocalizedModel>()
};
}
var attribute = await _specificationAttributeService.GetProductSpecificationAttributeByIdAsync(specificationId.Value)
?? throw new ArgumentException("No specification attribute found with the specified id");
//a vendor should have access only to his products
var currentVendor = await _workContext.GetCurrentVendorAsync();
if (currentVendor != null && (await _productService.GetProductByIdAsync(attribute.ProductId)).VendorId != currentVendor.Id)
throw new UnauthorizedAccessException("This is not your product");
var specAttributeOption = await _specificationAttributeService.GetSpecificationAttributeOptionByIdAsync(attribute.SpecificationAttributeOptionId);
var specAttribute = await _specificationAttributeService.GetSpecificationAttributeByIdAsync(specAttributeOption.SpecificationAttributeId);
var model = attribute.ToModel<AddSpecificationAttributeModel>();
model.SpecificationId = attribute.Id;
model.AttributeId = specAttribute.Id;
model.AttributeTypeName = await _localizationService.GetLocalizedEnumAsync(attribute.AttributeType);
model.AttributeName = specAttribute.Name;
model.AvailableAttributes = await (await _specificationAttributeService.GetSpecificationAttributesWithOptionsAsync())
.SelectAwait(async attributeWithOption =>
{View on GitHub (pinned to 64bdf2ff08)
Solutions
- Refresh the product specification list; the attribute no longer exists, so reopen a valid one.
- Verify the specificationId in the request corresponds to an existing ProductSpecificationAttribute row.
- Add a not-found guard that returns a friendly 'record no longer exists' message instead of an unhandled ArgumentException.
- Avoid deep-linking edit popups; always navigate from the current grid.
Example fix
// before
var attribute = await _specificationAttributeService.GetProductSpecificationAttributeByIdAsync(specificationId.Value)
?? throw new ArgumentException("No specification attribute found with the specified id");
// after (guard and redirect with message)
var attribute = await _specificationAttributeService.GetProductSpecificationAttributeByIdAsync(specificationId.Value);
if (attribute is null)
{
_notificationService.ErrorNotification("The specification attribute no longer exists.");
return RedirectToRoute(/* product spec list */);
} Defensive patterns
Strategy: validation
Validate before calling
// Validate the specification id before loading the editor.
var attribute = await _specificationAttributeService.GetProductSpecificationAttributeByIdAsync(specificationId.Value);
if (attribute is null)
{
_notificationService.ErrorNotification("This specification attribute no longer exists.");
return; // or redirect to the list
} Type guard
static bool SpecAttributeExists(ProductSpecificationAttribute a) => a is not null;
Try / catch
try { /* PrepareAddSpecificationAttributeModelAsync body */ }
catch (ArgumentException ex) when (ex.Message.Contains("specification attribute"))
{
_notificationService.ErrorNotification(ex.Message);
} Prevention
- Always navigate to the edit popup from the live grid, not a bookmarked id.
- Handle the 'deleted in another tab' case by re-checking existence before edit.
- Return a redirect/message instead of throwing ArgumentException for admin edit actions.
When it happens
Trigger: An admin request to edit a product specification attribute supplies a specificationId that resolves to no ProductSpecificationAttribute row. Triggered by following a stale edit link, deleting the attribute in another tab, or a malformed/guessed id.
Common situations: Concurrent admin edits where one user deletes the attribute while another opens its editor; bookmarked edit URLs after the attribute was removed; a bad/templated id passed from a custom integration; race between load and edit.
Related errors
- No activity log found with the specified id
- No address attribute value found with the specified id
- No comment found with the specified id
- No product category mapping found with the specified id
- No checkout attribute value found with the specified id
AI-assisted analysis of nopSolutions/nopCommerce@64bdf2ff08 (2026-08-13).
Data as JSON: /api/errors/e596c2c57e62c70a.
Report an issue: GitHub.