fullstackhero/dotnet-starter-kit · error · CustomException

Another brand with name

Error message

Another brand with name '{command.Name}' already exists.

What it means

After applying brand.Update (which recomputes the slug), UpdateBrandCommandHandler checks for another brand (b.Id != brand.Id) with the same Slug and throws CustomException with HTTP 409 Conflict if one exists. The rename is not saved. This is the update-time counterpart of the create-time uniqueness check.

Solutions

  1. Choose a name that does not collide with any other brand's slug
  2. Look up existing brands first to pick a unique name
  3. If both brands should be one, delete/merge instead of renaming

Example fix

// before
await mediator.Send(new UpdateBrandCommand(id, "Acme", ...)); // collides
// after
await mediator.Send(new UpdateBrandCommand(id, "Acme Europe", ...)); // unique slug
Defensive patterns

Strategy: validation

Validate before calling

var others = await mediator.Send(new SearchBrandsQuery(newName));
if (others.Items.Any(b => b.Id != id && b.Slug == Slugify(newName))) throw new InvalidOperationException("Name conflicts with another brand.");

Try / catch

try { await mediator.Send(new UpdateBrandCommand(id, newName, desc, logo)); }
catch (CustomException ex) when (ex.StatusCode == HttpStatusCode.Conflict) { /* show 'name already used' */ }

Prevention

When it happens

Trigger: Send/UpdateBrand command whose new Name slugifies to the Slug of a different existing brand.

Common situations: Renaming a brand to a name already used by another brand (case/punctuation differences slugify the same); two admins renaming concurrently; bulk rename scripts.

Related errors


AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15). Data as JSON: /api/errors/644a793e85b2a4f4. Report an issue: GitHub.

Appendix: source

Thrown at src/Modules/Catalog/Modules.Catalog/Features/v1/Brands/UpdateBrand/UpdateBrandCommandHandler.cs:29

    : ICommandHandler<UpdateBrandCommand, Guid>
{
    public async ValueTask<Guid> Handle(UpdateBrandCommand command, CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(command);

        var brand = await dbContext.Brands
            .FirstOrDefaultAsync(b => b.Id == command.BrandId, cancellationToken)
            .ConfigureAwait(false)
            ?? throw new NotFoundException($"Brand {command.BrandId} not found.");

        brand.Update(command.Name, command.Description, command.LogoUrl);

        bool slugTaken = await dbContext.Brands
            .AnyAsync(b => b.Slug == brand.Slug && b.Id != brand.Id, cancellationToken)
            .ConfigureAwait(false);
        if (slugTaken)
        {
            throw new CustomException(
                $"Another brand with name '{command.Name}' already exists.",
                (IEnumerable<string>?)null,
                HttpStatusCode.Conflict);
        }

        await dbContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
        return brand.Id;
    }
}

View on GitHub (pinned to 3f2959e683)