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
- Verify the tenantId exists in the tenant store before enqueueing the job.
- If the tenant was deleted intentionally, cancel/remove the queued job and its retries.
- Recreate the tenant and re-trigger provisioning if it should exist.
- 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
- Delete queued provisioning jobs when deleting a tenant.
- Validate tenant existence at enqueue time, not only inside the job.
- Limit Hangfire retry counts for jobs that depend on ephemeral rows.
- Log correlationId to trace the enqueue-to-run gap.
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
- Tenant not found for provisioning.
- Provisioning not found for tenant
- Provisioning for tenant not found.
- Invoice not found.
- Invoice not found.
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)