fullstackhero/dotnet-starter-kit · warning · NotFoundException
Product not found.
Error message
Product {command.ProductId} not found. What it means
ChangeProductPrice loads the product by command.ProductId and throws NotFoundException when no product matches, so a price change cannot be applied to a missing aggregate. Soft-deleted products are filtered out and also report 'not found'.
Solutions
- Verify the product id exists in the target database.
- Refresh the pricing source (re-export the feed) so ids are current.
- Handle the 404 per row in bulk price updates and log skipped ids.
- Check the product was not soft-deleted; restore it if the update should proceed.
Defensive patterns
Strategy: try-catch
Validate before calling
const exists = await api.listProducts({ ids: [productId] });
if (!exists.items.length) return skipPriceUpdate(productId, 'product not found'); Type guard
const isGuid = (v) => typeof v === 'string' && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v); Try / catch
try { await api.changeProductPrice(productId, amount, currency); }
catch (e) { if (e.status === 404) log(`Product ${productId} missing; skipped`); else throw e; } Prevention
- Regenerate pricing feeds shortly before applying them
- Verify the productId column mapping in import files
- Skip-and-log missing products in bulk updates
When it happens
Trigger: POST price-change for a ProductId that: (1) was deleted, (2) is a typo/fabricated Guid, (3) belongs to another tenant.
Common situations: Pricing feed pushing updates for products that were removed since the feed was generated; wrong column mapped to productId in a CSV import; stale browser tab submitting an old id.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15).
Data as JSON: /api/errors/b3ca287981be6b7f.
Report an issue: GitHub.
Appendix: source
Thrown at src/Modules/Catalog/Modules.Catalog/Features/v1/Products/ChangeProductPrice/ChangeProductPriceCommandHandler.cs:21
using FSH.Modules.Catalog.Contracts.v1.Products;
using FSH.Modules.Catalog.Data;
using FSH.Modules.Catalog.Domain;
using Mediator;
using Microsoft.EntityFrameworkCore;
namespace FSH.Modules.Catalog.Features.v1.Products.ChangeProductPrice;
public sealed class ChangeProductPriceCommandHandler(CatalogDbContext dbContext)
: ICommandHandler<ChangeProductPriceCommand, Guid>
{
public async ValueTask<Guid> Handle(ChangeProductPriceCommand command, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(command);
var product = await dbContext.Products
.FirstOrDefaultAsync(p => p.Id == command.ProductId, cancellationToken)
.ConfigureAwait(false)
?? throw new NotFoundException($"Product {command.ProductId} not found.");
product.ChangePrice(new Money(command.Amount, command.Currency));
await dbContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
return product.Id;
}
}
View on GitHub (pinned to 3f2959e683)