fullstackhero/dotnet-starter-kit · error · NotFoundException

Ticket not found.

Error message

Ticket {command.TicketId} not found.

What it means

UpdateTicket's handler fetches the ticket by TicketId with default (soft-delete + tenant) query filters and throws NotFoundException if no row matches. The handler refuses to update a nonexistent, soft-deleted, or out-of-tenant ticket, mapping the failure to the app's typed 404 exception.

Solutions

  1. Re-fetch the ticket list to confirm the ticket still exists and is not deleted before updating.
  2. If soft-deleted, call RestoreTicket first, then retry UpdateTicket.
  3. Verify the tenant context (header/subdomain) matches the ticket's tenant.
  4. Handle the 404 in the client (refresh form state) instead of blindly retrying.

Example fix

// before
await mutateUpdate({ id: staleId, title, description, priority }); // 404
// after
const res = await getTicket(staleId);
if (!res) { refreshList(); notify('Ticket no longer exists'); return; }
await mutateUpdate({ id: staleId, title, description, priority });
Defensive patterns

Strategy: try-catch

Validate before calling

const ticket = await api.getTicket(id);
if (!ticket || ticket.deleted) { refreshForm(); return; }

Try / catch

try {
  await updateTicket({ id, title, description, priority });
} catch (ApiError e) when (e.Status === 404) {
  resetEditForm();
  notify('Ticket was deleted by another user');
}

Prevention

When it happens

Trigger: Submitting UpdateTicket (title/description/priority changes) for a TicketId that doesn't exist, was soft-deleted, or lives in another tenant; a stale UI form holding an id of a ticket deleted concurrently by another user.

Common situations: Two operators editing the same ticket list, one deletes while the other saves; admin app and dashboard app pointing at different tenants with a copied link; automated scripts replaying updates for tickets purged in the meantime.

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

Appendix: source

Thrown at src/Modules/Tickets/Modules.Tickets/Features/v1/Tickets/UpdateTicket/UpdateTicketCommandHandler.cs:19

using FSH.Framework.Core.Exceptions;
using FSH.Modules.Tickets.Contracts.v1.Tickets;
using FSH.Modules.Tickets.Data;
using Mediator;
using Microsoft.EntityFrameworkCore;

namespace FSH.Modules.Tickets.Features.v1.Tickets.UpdateTicket;

public sealed class UpdateTicketCommandHandler(TicketsDbContext dbContext)
    : ICommandHandler<UpdateTicketCommand, Guid>
{
    public async ValueTask<Guid> Handle(UpdateTicketCommand command, CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(command);

        var ticket = await dbContext.Tickets
            .FirstOrDefaultAsync(t => t.Id == command.TicketId, cancellationToken)
            .ConfigureAwait(false)
            ?? throw new NotFoundException($"Ticket {command.TicketId} not found.");

        ticket.UpdateDetails(command.Title, command.Description, command.Priority);
        await dbContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
        return ticket.Id;
    }
}

View on GitHub (pinned to 3f2959e683)