fullstackhero/dotnet-starter-kit · error · NotFoundException

Webhook subscription

Error message

Webhook subscription {command.Id} not found.

What it means

DeleteWebhookSubscription's handler loads the subscription by command Id and throws NotFoundException when none matches, before calling Remove. The webhook module therefore rejects deletion of unknown, soft-deleted/filtered, or out-of-tenant subscriptions with a typed not-found (HTTP 404) instead of silently doing nothing.

Solutions

  1. Treat the 404 as success for idempotent delete UX (the desired end state — subscription gone — is already achieved).
  2. Refresh the subscription list before deleting to confirm it still exists.
  3. Check the tenant context matches where the subscription was created.
  4. Verify the GUID is copied from the correct environment's list endpoint.

Example fix

// before (client)
await apiFetch(`/webhooks/v1/subscriptions/${id}`, { method: 'DELETE' }); // 404 on double delete
// after
try {
  await apiFetch(`/webhooks/v1/subscriptions/${id}`, { method: 'DELETE' });
} catch (e) {
  if (e.status !== 404) throw e; // idempotent: 404 already deleted
}
Defensive patterns

Strategy: try-catch

Validate before calling

const sub = await api.getSubscription(id);
if (!sub) return; // already gone — delete goal achieved

Try / catch

try {
  await deleteSubscription(id);
} catch (ApiError e) when (e.Status === 404) {
  // idempotent success
  removeFromLocalList(id);
}

Prevention

When it happens

Trigger: Calling DeleteWebhookSubscription with a subscription Id that was already deleted (second delete of the same id), an id from another tenant, or a fabricated/mistyped GUID.

Common situations: Double-clicking a delete button so the second request 404s; a client list that wasn't refreshed after another admin removed the subscription; copying an id from logs of a different environment (staging vs production).

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

Appendix: source

Thrown at src/Modules/Webhooks/Modules.Webhooks/Features/v1/DeleteWebhookSubscription/DeleteWebhookSubscriptionCommandHandler.cs:19

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

namespace FSH.Modules.Webhooks.Features.v1.DeleteWebhookSubscription;

public sealed class DeleteWebhookSubscriptionCommandHandler(
    WebhookDbContext dbContext) : ICommandHandler<DeleteWebhookSubscriptionCommand>
{
    public async ValueTask<Unit> Handle(DeleteWebhookSubscriptionCommand command, CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(command);

        var subscription = await dbContext.Subscriptions
            .FirstOrDefaultAsync(s => s.Id == command.Id, cancellationToken)
            .ConfigureAwait(false)
            ?? throw new NotFoundException($"Webhook subscription {command.Id} not found.");

        dbContext.Subscriptions.Remove(subscription);
        await dbContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false);

        return Unit.Value;
    }
}

View on GitHub (pinned to 3f2959e683)