fullstackhero/dotnet-starter-kit · error · CustomException
Another product with name
Error message
Another product with name '{command.Name}' already exists. What it means
After updating, the handler slugifies the product name and checks whether another product already uses that slug; if so it throws CustomException with HTTP 409 Conflict — product names (via slugs) must be unique per module rules.
Solutions
- Pick a different product name (add a variant/suffix) and retry.
- Check the existing product list for the colliding name before saving.
- If the two products should be one, delete/merge the duplicate instead of renaming.
- Catch CustomException with the 409 status in the client and show a friendly 'name taken' message.
Example fix
// before
await mediator.Send(new UpdateProductCommand { ProductId = id, Name = newName });
// after
var slug = newName.ToSlug();
bool taken = await db.Products.AnyAsync(p => p.Slug == slug && p.Id != id, ct);
if (taken) newName = $"{newName} 2"; // or prompt user
await mediator.Send(new UpdateProductCommand { ProductId = id, Name = newName }, ct); Defensive patterns
Strategy: try-catch
Validate before calling
var slug = newName.ToSlug();
bool taken = await dbContext.Products.AnyAsync(p => p.Slug == slug && p.Id != productId, ct);
if (taken) throw new ValidationException("Another product already uses this name."); Try / catch
try { await mediator.Send(cmd, ct); }
catch (CustomException ex) when (ex.StatusCode == HttpStatusCode.Conflict)
{ ModelState.AddModelError(nameof(cmd.Name), "Product name already in use"); return Results.Conflict(); } Prevention
- Pre-check slug availability (debounced API check) in the rename form.
- Remember slugify collapses casing/punctuation — 'Pro X' and 'Pro X!' collide.
- In bulk imports, generate unique slugs (append counter) instead of failing.
- Show 409 as a user-facing 'name taken' message, not a generic error.
When it happens
Trigger: UpdateProductCommand renaming a product to a name whose generated slug matches another product's slug (p.Slug == product.Slug && p.Id != product.Id). Also fires when only casing/punctuation changes, since slugify normalizes them to the same slug.
Common situations: Two editors rename different products to the same title; renaming 'Pro X' when 'Pro X' already exists (identical slugs); bulk import scripts not checking name collisions.
Related errors
- A product with name ' ' already exists.
- A product with SKU ' ' already exists.
- A brand with name ' ' already exists.
- Another brand with name
- Another category with name
AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15).
Data as JSON: /api/errors/4c7da8ca76e5b3e6.
Report an issue: GitHub.
Appendix: source
Thrown at src/Modules/Catalog/Modules.Catalog/Features/v1/Products/UpdateProduct/UpdateProductCommandHandler.cs:56
if (!categoryExists)
{
throw new NotFoundException($"Category {command.CategoryId} not found.");
}
}
product.Update(
command.Name,
command.Description,
command.BrandId,
command.CategoryId,
command.IsActive);
bool slugTaken = await dbContext.Products
.AnyAsync(p => p.Slug == product.Slug && p.Id != product.Id, cancellationToken)
.ConfigureAwait(false);
if (slugTaken)
{
throw new CustomException(
$"Another product with name '{command.Name}' already exists.",
(IEnumerable<string>?)null,
HttpStatusCode.Conflict);
}
await dbContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
return product.Id;
}
}
View on GitHub (pinned to 3f2959e683)