fullstackhero/dotnet-starter-kit · error · CustomException

A category with name

Error message

A category with name '{command.Name}' already exists.

What it means

CreateCategoryCommandHandler computes the category slug from the name and throws CustomException with HTTP 409 Conflict when an existing category already has that Slug; nothing is persisted. Slug collisions arise from identical or near-identical names.

Solutions

  1. Use a different category name (or explicit unique slug)
  2. Check the existing category — reuse or update it instead of creating
  3. If the duplicate is soft-deleted, restore or purge it first

Example fix

// before
await mediator.Send(new CreateCategoryCommand("Shoes", null, null)); // second time
// after
await mediator.Send(new CreateCategoryCommand("Shoes Outlet", null, null));
Defensive patterns

Strategy: validation

Validate before calling

var existing = await mediator.Send(new SearchCategoriesQuery(name));
if (existing.Items.Any(c => c.Slug == Slugify(name))) throw new InvalidOperationException("Category name already exists.");

Type guard

bool IsNonEmptyName(string? n) => !string.IsNullOrWhiteSpace(n);

Try / catch

try { await mediator.Send(new CreateCategoryCommand(name, desc, parentId)); }
catch (CustomException ex) when (ex.StatusCode == HttpStatusCode.Conflict) { /* prompt for a different name */ }

Prevention

When it happens

Trigger: Send/CreateCategory command whose Name slugifies to the Slug of an existing category in the tenant.

Common situations: Re-running an import/seed that creates categories; names differing only by case/punctuation; creating the same category in parallel requests.

Related errors


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

Appendix: source

Thrown at src/Modules/Catalog/Modules.Catalog/Features/v1/Categories/CreateCategory/CreateCategoryCommandHandler.cs:36

        if (command.ParentCategoryId is { } parentId)
        {
            bool parentExists = await dbContext.Categories
                .AnyAsync(c => c.Id == parentId, cancellationToken)
                .ConfigureAwait(false);
            if (!parentExists)
            {
                throw new NotFoundException($"Parent category {parentId} not found.");
            }
        }

        var category = Category.Create(command.Name, command.Description, command.ParentCategoryId);

        bool slugTaken = await dbContext.Categories
            .AnyAsync(c => c.Slug == category.Slug, cancellationToken)
            .ConfigureAwait(false);
        if (slugTaken)
        {
            throw new CustomException(
                $"A category with name '{command.Name}' already exists.",
                (IEnumerable<string>?)null,
                HttpStatusCode.Conflict);
        }

        dbContext.Categories.Add(category);
        await dbContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
        return category.Id;
    }
}

View on GitHub (pinned to 3f2959e683)