fullstackhero/dotnet-starter-kit · error · NotFoundException

Brand not found.

Error message

Brand {query.BrandId} not found.

What it means

GetBrandByIdQueryHandler queries dbContext.Brands (AsNoTracking) for the given BrandId and throws NotFoundException when no row matches, which the API surfaces as HTTP 404. Default query filters (soft-delete and tenant scoping) apply, so hidden or foreign-tenant rows look missing.

Solutions

  1. Confirm the BrandId via the brands list endpoint
  2. Restore the brand if it was soft-deleted (RestoreBrand endpoint)
  3. Verify the tenant header matches the tenant owning the brand
Defensive patterns

Strategy: try-catch

Validate before calling

bool exists = brands.Any(b => b.Id == id); // from a recently fetched list

Try / catch

try { var brand = await mediator.Send(new GetBrandByIdQuery(id)); }
catch (NotFoundException) { return Results.NotFound($"Brand {id} not found."); }

Prevention

When it happens

Trigger: Send/GetBrandById query with an unknown, hard-deleted, soft-deleted, or cross-tenant BrandId.

Common situations: Client cached an ID that was since deleted; user opens a bookmarked URL after the brand was removed; multitenancy header misconfigured so the row is invisible.

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/f12034b6f4190391. Report an issue: GitHub.

Appendix: source

Thrown at src/Modules/Catalog/Modules.Catalog/Features/v1/Brands/GetBrandById/GetBrandByIdQueryHandler.cs:21

using FSH.Modules.Catalog.Contracts.v1.Brands;
using FSH.Modules.Catalog.Data;
using Mediator;
using Microsoft.EntityFrameworkCore;

namespace FSH.Modules.Catalog.Features.v1.Brands.GetBrandById;

public sealed class GetBrandByIdQueryHandler(CatalogDbContext dbContext)
    : IQueryHandler<GetBrandByIdQuery, BrandDto>
{
    public async ValueTask<BrandDto> Handle(GetBrandByIdQuery query, CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(query);

        var brand = await dbContext.Brands
            .AsNoTracking()
            .FirstOrDefaultAsync(b => b.Id == query.BrandId, cancellationToken)
            .ConfigureAwait(false)
            ?? throw new NotFoundException($"Brand {query.BrandId} not found.");

        return new BrandDto(
            brand.Id,
            brand.Name,
            brand.Slug,
            brand.Description,
            brand.LogoUrl,
            brand.CreatedAtUtc,
            brand.UpdatedAtUtc,
            brand.DeletedOnUtc,
            brand.DeletedBy);
    }
}

View on GitHub (pinned to 3f2959e683)