fullstackhero/dotnet-starter-kit · error · NotFoundException

Tenant not found during provisioning.

Error message

Tenant {tenantId} not found during provisioning.

What it means

TenantProvisioningJob.RunAsync throws NotFoundException ("Tenant {tenantId} not found during provisioning.") when the background job starts but the tenant row no longer exists in the tenant store. The provisioning run cannot proceed without the tenant record.

Solutions

  1. Verify the tenantId exists in the tenant store before enqueueing the job.
  2. If the tenant was deleted intentionally, cancel/remove the queued job and its retries.
  3. Recreate the tenant and re-trigger provisioning if it should exist.
  4. Check job arguments/logs for a corrupted or truncated tenant id.

Example fix

// before
await backgroundJobClient.EnqueueAsync<TenantProvisioningJob>(j => j.RunAsync(tenantId, corrId, ct));
// after
if (await _tenantStore.GetAsync(tenantId) is null)
    throw new ValidationException($"Cannot provision: tenant {tenantId} does not exist.");
await backgroundJobClient.EnqueueAsync<TenantProvisioningJob>(j => j.RunAsync(tenantId, corrId, ct));
Defensive patterns

Strategy: validation

Validate before calling

var tenant = await tenantStore.GetAsync(tenantId);
if (tenant is null) throw new ValidationException($"Tenant {tenantId} missing; not enqueueing provisioning.");

Try / catch

try { await job.RunAsync(tenantId, corrId); }
catch (NotFoundException) { logger.LogWarning("Skipping provisioning; tenant {TenantId} gone", tenantId); }

Prevention

When it happens

Trigger: Enqueueing provisioning for a tenant id that was deleted between enqueue and job execution; a Hangfire retry firing after tenant cleanup; passing a wrong/typo'd tenant id when scheduling the job.

Common situations: Hangfire retries firing after the tenant was removed in a rollback; tests or scripts enqueueing provisioning for fabricated ids; tenant deletion racing with queued provisioning.

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

Appendix: source

Thrown at src/Modules/Multitenancy/Modules.Multitenancy/Provisioning/TenantProvisioningJob.cs:37

    public TenantProvisioningJob(
        ITenantProvisioningService provisioningService,
        IMultiTenantStore<AppTenantInfo> tenantStore,
        IMultiTenantContextSetter tenantContextSetter,
        ITenantService tenantService,
        ILogger<TenantProvisioningJob> logger)
    {
        _provisioningService = provisioningService;
        _tenantStore = tenantStore;
        _tenantContextSetter = tenantContextSetter;
        _tenantService = tenantService;
        _logger = logger;
    }

    public async Task RunAsync(string tenantId, string correlationId, CancellationToken cancellationToken = default)
    {
        var tenant = await _tenantStore.GetAsync(tenantId).ConfigureAwait(false)
            ?? throw new NotFoundException($"Tenant {tenantId} not found during provisioning.");

        var currentStep = TenantProvisioningStepName.Database;
        try
        {
            var runDatabase = await _provisioningService.MarkRunningAsync(tenantId, correlationId, currentStep, cancellationToken).ConfigureAwait(false);

            _tenantContextSetter.MultiTenantContext = new MultiTenantContext<AppTenantInfo>(tenant);

            if (runDatabase)
            {
                await _provisioningService.MarkStepCompletedAsync(tenantId, correlationId, currentStep, cancellationToken).ConfigureAwait(false);
            }

            currentStep = TenantProvisioningStepName.Migrations;
            var runMigrations = await _provisioningService.MarkRunningAsync(tenantId, correlationId, currentStep, cancellationToken).ConfigureAwait(false);
            if (runMigrations)
            {
                await _tenantService.MigrateTenantAsync(tenant, cancellationToken).ConfigureAwait(false);

View on GitHub (pinned to 3f2959e683)