fullstackhero/dotnet-starter-kit · error · CustomException

A product with name ' ' already exists.

Error message

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

What it means

CreateProductCommandHandler checks whether the product's generated Slug collides with an existing product's Slug. If taken, it throws CustomException with HttpStatusCode.Conflict (HTTP 409). Slug uniqueness backs the product URL, so a name that slugifies to an existing slug is rejected.

Solutions

  1. Choose a different product name so the generated slug is unique, or append a distinguishing suffix (model number, variant).
  2. Search products by name/slug first and reuse or rename the existing entry.
  3. If your flow controls slug generation, add a uniqueness suffix to the slug client-side before submitting.
  4. Handle HTTP 409 in the client by prompting the user for a new name instead of failing silently.

Example fix

// before
await api.createProduct({ sku: sku, name: 'Cool Widget' });
// after
const slug = slugify('Cool Widget');
const taken = await api.searchProducts({ slug });
const name = taken.items.length > 0 ? `Cool Widget ${Date.now()}` : 'Cool Widget';
await api.createProduct({ sku: sku, name: name });
Defensive patterns

Strategy: validation

Validate before calling

const slug = slugify(name);
const dup = await api.searchProducts({ slug });
if (dup.items.length > 0) throw new Error(`A product named "${name}" already exists`);

Try / catch

try {
  await api.createProduct(payload);
} catch (e) {
  if (e.status === 409) {
    showFieldError('name', 'A product with this name already exists');
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: POST /products (v1) where the slug derived from command.Name (or product.Slug) equals an existing product's Slug — e.g. creating 'Cool Widget' when a product named 'Cool Widget' (or 'Cool Widget!') already slugified to the same value.

Common situations: Re-creating a product that was soft-deleted? No — more commonly: two products with names differing only by punctuation/case; importing a catalog with duplicate names; retry after a successful create.

Related errors


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

Appendix: source

Thrown at src/Modules/Catalog/Modules.Catalog/Features/v1/Products/CreateProduct/CreateProductCommandHandler.cs:60

            command.Stock);

        bool skuTaken = await dbContext.Products
            .AnyAsync(p => p.Sku == product.Sku, cancellationToken)
            .ConfigureAwait(false);
        if (skuTaken)
        {
            throw new CustomException(
                $"A product with SKU '{product.Sku}' already exists.",
                (IEnumerable<string>?)null,
                HttpStatusCode.Conflict);
        }

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

        dbContext.Products.Add(product);
        await dbContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
        return product.Id;
    }
}

View on GitHub (pinned to 3f2959e683)