nopSolutions/nopCommerce · warning · Exception
{ModelState errors joined by ', '}
Error message
{ModelState errors joined by ', '} What it means
Thrown in EditAddressAsync when ModelState is invalid. The controller collects every ModelState error message, joins them with ', ', and throws a single Exception whose message is that joined string. The surrounding try/catch (line 304) logs it as a warning and returns it to the client as JSON { error = 1, message }. So this is not a server crash but a surfaced validation summary — the message is dynamically composed from the model validation failures.
Source
Thrown at src/Presentation/Nop.Web/Controllers/CheckoutController.cs:277
if (vatNumberStatus != VatNumberStatus.Valid && !string.IsNullOrEmpty(fullVatNumber))
{
var warning = await _localizationService.GetResourceAsync("Checkout.VatNumber.Warning");
return string.Format(warning, await _localizationService.GetLocalizedEnumAsync(vatNumberStatus));
}
return string.Empty;
}
protected virtual async Task<JsonResult> EditAddressAsync(AddressModel addressModel, IFormCollection form, Func<Customer, IList<ShoppingCartItem>, Address, Task<JsonResult>> getResult)
{
try
{
if (!ModelState.IsValid)
{
var errors = string.Join(", ", ModelState.Values.Where(p => p.Errors.Any()).SelectMany(p => p.Errors)
.Select(p => p.ErrorMessage));
throw new Exception(errors);
}
var customer = await _workContext.GetCurrentCustomerAsync();
var store = await _storeContext.GetCurrentStoreAsync();
var cart = await _shoppingCartService.GetShoppingCartAsync(customer, ShoppingCartType.ShoppingCart, store.Id);
if (!cart.Any())
throw new Exception("Your cart is empty");
//find address (ensure that it belongs to the current customer)
var address = await _customerService.GetCustomerAddressAsync(customer.Id, addressModel.Id)
?? throw new Exception("Address can't be loaded");
//custom address attributes
var customAttributes = await _addressAttributeParser.ParseCustomAttributesAsync(form, NopCommonDefaults.AddressAttributeControlName);
var customAttributeWarnings = await _addressAttributeParser.GetAttributeWarningsAsync(customAttributes);
if (customAttributeWarnings.Any())
return Json(new { error = 1, message = customAttributeWarnings });
View on GitHub (pinned to 64bdf2ff08)
Solutions
- Fix the failing address fields per the joined messages shown in the JSON response.
- Ensure client-side unobtrusive validation is enabled so invalid posts are prevented before submit.
- Review custom AddressModel validation attributes and loosen/fix over-strict rules.
- If messages are keys rather than text, verify localization resources are loaded for the address fields.
Example fix
// before
if (!ModelState.IsValid)
{
var errors = string.Join(", ", ModelState.Values.Where(p => p.Errors.Any()).SelectMany(p => p.Errors)
.Select(p => p.ErrorMessage));
throw new Exception(errors);
}
// after (return structured validation JSON)
if (!ModelState.IsValid)
{
var errors = ModelState.Values.SelectMany(p => p.Errors).Select(p => p.ErrorMessage).ToList();
return Json(new { error = 1, message = string.Join(", ", errors), fieldErrors = errors });
} Defensive patterns
Strategy: validation
Validate before calling
// Validate on the client before POST (Razor Pages / MVC unobtrusive validation):
// ensure required address fields (Country, StateProvince, City, ZipPostalCode) are filled.
// Server-side: inspect ModelState without throwing.
if (!ModelState.IsValid)
{
var errors = ModelState.Values.SelectMany(p => p.Errors).Select(p => p.ErrorMessage).ToList();
return Json(new { error = 1, message = string.Join(", ", errors) });
} Try / catch
// Already wrapped: the controller catches Exception and returns JSON.
catch (Exception exc)
{
await _logger.WarningAsync(exc.Message, exc, await _workContext.GetCurrentCustomerAsync());
return Json(new { error = 1, message = exc.Message });
} Prevention
- Enable client-side unobtrusive validation so invalid posts never reach the server.
- Review custom AddressModel validation attributes for over-strict rules.
- Ensure localization resources exist for all address-field validation messages.
When it happens
Trigger: A billing/shipping address edit POST fails model validation (required fields empty, format violations, attribute constraints). ModelState.Values contains errors; they are concatenated and returned. Common with missing country/zip or invalid email-length rules.
Common situations: Customer submits address form with missing required fields (city, zip, phone); custom address attributes with validation rules fail; localized required-field messages get concatenated; client-side validation bypassed or disabled.
Related errors
- Checkout.Address.NotFound
- Shipping address is not provided
- Cart is empty
- {warning1};{warning2};...
- Billing address is not provided
AI-assisted analysis of nopSolutions/nopCommerce@64bdf2ff08 (2026-08-13).
Data as JSON: /api/errors/5b7ffdf6375ee540.
Report an issue: GitHub.