elsa-workflows/elsa-core · error · InvalidOperationException
AI conversation entity metadata was not found.
Error message
AI conversation entity metadata was not found.
What it means
EFCoreAIConversationCleanup resolves the mapped table name for AIConversationRecord from the EF Core model. If FindEntityType returns null, the AIConversationRecord entity was never added to AIDbContext's model, so cleanup throws InvalidOperationException. This usually indicates a mismatched or misconfigured model.
Solutions
- Register AIConversationRecord in the AIDbContext model (DbSet and/or OnModelCreating mapping).
- Ensure cleanup runs against the real AIDbContext, not a substitute context.
- Regenerate/rebuild the EF model after package upgrades.
- Verify no custom IModelConfiguration removes the entity mapping.
Example fix
// before
class MyAIDbContext : DbContext { }
// after
class MyAIDbContext : DbContext {
public DbSet<AIConversationRecord> Conversations => Set<AIConversationRecord>();
} Defensive patterns
Strategy: validation
Validate before calling
var entityType = dbContext.Model.FindEntityType(typeof(AIConversationRecord));
if (entityType is null) throw new InvalidOperationException("AIConversationRecord not mapped in AIDbContext model"); Type guard
bool IsConversationMapped(AIDbContext db) => db.Model.FindEntityType(typeof(AIConversationRecord)) is not null;
Try / catch
try { await cleanup.RunAsync(ct); } catch (InvalidOperationException ex) when (ex.Message.Contains("entity metadata")) { logger.LogError(ex, "AIDbContext model missing AIConversationRecord"); } Prevention
- Keep AIConversationRecord mapped in every AIDbContext derivative.
- Use the module's default AIDbContext rather than custom substitutes for cleanup.
- Re-check the EF model after upgrading persistence packages.
When it happens
Trigger: Running cleanup against an AIDbContext whose model does not include AIConversationRecord (e.g. wrong DbContext instance, model built without the entity, or an outdated/overridden OnModelCreating).
Common situations: Using a hand-built ModelBuilder in tests that omits the entity; replacing AIDbContext with a custom context that forgets the DbSet/mapping; stale model caches after upgrading the module.
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 conversation table metadata was not found.
- Register with configured before calling , or call with a…
- Cannot overwrite an AI conversation that belongs to another…
- Failed to insert AI conversation
- A replacement-compensation link refers to a deleted user…
AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13).
Data as JSON: /api/errors/48ba9093cc30580a.
Report an issue: GitHub.
Appendix: source
Thrown at src/modules/Elsa.AI.Persistence.EFCore/Services/EFCoreAIConversationCleanup.cs:48
var tableName = ResolveConversationTableName(dbContext);
var sql = $@"DELETE FROM {QuoteSqliteIdentifier(tableName)}
WHERE ""RetentionMode"" = {{0}}
AND ""RetentionExpiresAt"" IS NOT NULL
AND ""RetentionExpiresAt"" <= {{1}}";
return await dbContext.Database.ExecuteSqlRawAsync(
sql,
[configuredRetentionMode, now],
cancellationToken);
}
return await dbContext.Conversations
.Where(x => x.RetentionMode == configuredRetentionMode && x.RetentionExpiresAt != null && x.RetentionExpiresAt <= now)
.ExecuteDeleteAsync(cancellationToken);
}
private static string ResolveConversationTableName(AIDbContext dbContext)
{
var entityType = dbContext.Model.FindEntityType(typeof(AIConversationRecord)) ?? throw new InvalidOperationException("AI conversation entity metadata was not found.");
return entityType.GetTableName() ?? throw new InvalidOperationException("AI conversation table metadata was not found.");
}
private static bool IsSqliteProvider(string? providerName) =>
providerName?.Contains("Sqlite", StringComparison.OrdinalIgnoreCase) == true;
private static string QuoteSqliteIdentifier(string identifier) => $"\"{identifier.Replace("\"", "\"\"", StringComparison.Ordinal)}\"";
}
View on GitHub (pinned to fe9217bdfa)