fullstackhero/dotnet-starter-kit · error · NotFoundException
Brand not found.
Error message
Brand {command.BrandId} not found. What it means
UpdateBrandCommandHandler loads the brand by command.BrandId and throws NotFoundException when no row matches; the API maps it to HTTP 404 and the update is aborted. Soft-deleted and cross-tenant rows are hidden by query filters, so they also appear as not found.
Solutions
- Re-fetch the brand list to confirm the BrandId still exists
- Re-create the brand if it was (soft-)deleted
- Ensure the request carries the correct tenant header
Defensive patterns
Strategy: try-catch
Validate before calling
var brand = await mediator.Send(new GetBrandByIdQuery(id)); // throws 404 early if gone
Try / catch
try { await mediator.Send(new UpdateBrandCommand(id, name, desc, logo)); }
catch (NotFoundException) { /* reload list; entity vanished */ } Prevention
- Use optimistic concurrency / re-fetch before edit forms
- Keep stale IDs out of cached edit pages
- Confirm tenant context before updates
When it happens
Trigger: Send/UpdateBrand command with a BrandId that does not exist, was deleted, or belongs to a different tenant.
Common situations: Editing from a stale list page after another user deleted the brand; wrong tenant context; ID copy/paste mistake.
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/fd8b3aaa679485c0.
Report an issue: GitHub.
Appendix: source
Thrown at src/Modules/Catalog/Modules.Catalog/Features/v1/Brands/UpdateBrand/UpdateBrandCommandHandler.cs:20
using FSH.Framework.Core.Exceptions;
using FSH.Modules.Catalog.Contracts.v1.Brands;
using FSH.Modules.Catalog.Data;
using Mediator;
using Microsoft.EntityFrameworkCore;
namespace FSH.Modules.Catalog.Features.v1.Brands.UpdateBrand;
public sealed class UpdateBrandCommandHandler(CatalogDbContext dbContext)
: 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)