{"record":{"id":"48ba9093cc30580a","repo":"elsa-workflows/elsa-core","slug":"ai-conversation-entity-metadata-was-not-found","errorCode":null,"errorMessage":"AI conversation entity metadata was not found.","messagePattern":"AI conversation entity metadata was not found\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.AI.Persistence.EFCore/Services/EFCoreAIConversationCleanup.cs","lineNumber":48,"sourceCode":"            var tableName = ResolveConversationTableName(dbContext);\n            var sql = $@\"DELETE FROM {QuoteSqliteIdentifier(tableName)}\nWHERE \"\"RetentionMode\"\" = {{0}}\n  AND \"\"RetentionExpiresAt\"\" IS NOT NULL\n  AND \"\"RetentionExpiresAt\"\" <= {{1}}\";\n            return await dbContext.Database.ExecuteSqlRawAsync(\n                sql,\n                [configuredRetentionMode, now],\n                cancellationToken);\n        }\n\n        return await dbContext.Conversations\n            .Where(x => x.RetentionMode == configuredRetentionMode && x.RetentionExpiresAt != null && x.RetentionExpiresAt <= now)\n            .ExecuteDeleteAsync(cancellationToken);\n    }\n\n    private static string ResolveConversationTableName(AIDbContext dbContext)\n    {\n        var entityType = dbContext.Model.FindEntityType(typeof(AIConversationRecord)) ?? throw new InvalidOperationException(\"AI conversation entity metadata was not found.\");\n        return entityType.GetTableName() ?? throw new InvalidOperationException(\"AI conversation table metadata was not found.\");\n    }\n\n    private static bool IsSqliteProvider(string? providerName) =>\n        providerName?.Contains(\"Sqlite\", StringComparison.OrdinalIgnoreCase) == true;\n\n    private static string QuoteSqliteIdentifier(string identifier) => $\"\\\"{identifier.Replace(\"\\\"\", \"\\\"\\\"\", StringComparison.Ordinal)}\\\"\";\n}\n","sourceCodeStart":30,"sourceCodeEnd":57,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.AI.Persistence.EFCore/Services/EFCoreAIConversationCleanup.cs#L30-L57","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\nclass MyAIDbContext : DbContext { }\n// after\nclass MyAIDbContext : DbContext {\n    public DbSet<AIConversationRecord> Conversations => Set<AIConversationRecord>();\n}","handlingStrategy":"validation","validationCode":"var entityType = dbContext.Model.FindEntityType(typeof(AIConversationRecord));\nif (entityType is null) throw new InvalidOperationException(\"AIConversationRecord not mapped in AIDbContext model\");","typeGuard":"bool IsConversationMapped(AIDbContext db) => db.Model.FindEntityType(typeof(AIConversationRecord)) is not null;","tryCatchPattern":"try { await cleanup.RunAsync(ct); } catch (InvalidOperationException ex) when (ex.Message.Contains(\"entity metadata\")) { logger.LogError(ex, \"AIDbContext model missing AIConversationRecord\"); }","preventionTips":["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."],"tags":["dotnet","ef-core","cleanup","model-metadata"],"backgroundTag":"entity-not-found","analyzedSha":"fe9217bdfa0e27f0e09e45006eb6898f616e513d","analyzedAt":"2026-09-13T20:32:34.702Z","contentChangedAt":"2026-09-13T20:32:34.702Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}