{"record":{"id":"1f127f17d8acc205","repo":"fullstackhero/dotnet-starter-kit","slug":"a-product-with-name-command-name-already-exists","errorCode":null,"errorMessage":"A product with name '{command.Name}' already exists.","messagePattern":"A product with name '(.+?)' already exists\\.","errorType":"exception","errorClass":"CustomException","httpStatus":409,"severity":"error","filePath":"src/Modules/Catalog/Modules.Catalog/Features/v1/Products/CreateProduct/CreateProductCommandHandler.cs","lineNumber":60,"sourceCode":"            command.Stock);\n\n        bool skuTaken = await dbContext.Products\n            .AnyAsync(p => p.Sku == product.Sku, cancellationToken)\n            .ConfigureAwait(false);\n        if (skuTaken)\n        {\n            throw new CustomException(\n                $\"A product with SKU '{product.Sku}' already exists.\",\n                (IEnumerable<string>?)null,\n                HttpStatusCode.Conflict);\n        }\n\n        bool slugTaken = await dbContext.Products\n            .AnyAsync(p => p.Slug == product.Slug, cancellationToken)\n            .ConfigureAwait(false);\n        if (slugTaken)\n        {\n            throw new CustomException(\n                $\"A product with name '{command.Name}' already exists.\",\n                (IEnumerable<string>?)null,\n                HttpStatusCode.Conflict);\n        }\n\n        dbContext.Products.Add(product);\n        await dbContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false);\n        return product.Id;\n    }\n}\n","sourceCodeStart":42,"sourceCodeEnd":71,"githubUrl":"https://github.com/fullstackhero/dotnet-starter-kit/blob/3f2959e683e9f83f13e55e1678c9119f63c7e8e5/src/Modules/Catalog/Modules.Catalog/Features/v1/Products/CreateProduct/CreateProductCommandHandler.cs#L42-L71","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Choose a different product name so the generated slug is unique, or append a distinguishing suffix (model number, variant).","Search products by name/slug first and reuse or rename the existing entry.","If your flow controls slug generation, add a uniqueness suffix to the slug client-side before submitting.","Handle HTTP 409 in the client by prompting the user for a new name instead of failing silently."],"exampleFix":"// before\nawait api.createProduct({ sku: sku, name: 'Cool Widget' });\n// after\nconst slug = slugify('Cool Widget');\nconst taken = await api.searchProducts({ slug });\nconst name = taken.items.length > 0 ? `Cool Widget ${Date.now()}` : 'Cool Widget';\nawait api.createProduct({ sku: sku, name: name });","handlingStrategy":"validation","validationCode":"const slug = slugify(name);\nconst dup = await api.searchProducts({ slug });\nif (dup.items.length > 0) throw new Error(`A product named \"${name}\" already exists`);","typeGuard":null,"tryCatchPattern":"try {\n  await api.createProduct(payload);\n} catch (e) {\n  if (e.status === 409) {\n    showFieldError('name', 'A product with this name already exists');\n    return;\n  }\n  throw e;\n}","preventionTips":["Show live 'name taken' feedback as the user types","Normalize names (case/punctuation) before uniqueness checks client-side","Append variant/model suffixes to distinguish similar product names"],"tags":["conflict","duplicate","slug","catalog","http-409"],"backgroundTag":"duplicate-resource-conflict","analyzedSha":"3f2959e683e9f83f13e55e1678c9119f63c7e8e5","analyzedAt":"2026-09-15T22:20:53.684Z","contentChangedAt":"2026-09-15T22:20:53.684Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}