elsa-workflows/elsa-core · critical · InvalidOperationException
Register with configured before calling , or call with a…
Error message
Register {nameof(AIDbContext)} with configured {nameof(DbContextOptions<AIDbContext>)} before calling {nameof(AddAIPersistenceStores)}, or call {nameof(AddAIPersistenceStores)} with a database provider configuration. What it means
AddAIPersistenceStores needs a configured DbContextOptions<AIDbContext> in the service collection. If none is registered and no configureDbContext delegate is supplied, it throws InvalidOperationException because EF Core could not build AIDbContext. The method can either receive a provider configuration delegate or find pre-registered DbContext options.
Solutions
- Pass a provider configuration: AddAIPersistenceStores(o => o.UseSqlite(connectionString)).
- Register options first via AddDbContext<AIDbContext>(...) before calling AddAIPersistenceStores().
- Check the order of extension calls so the options registration happens earlier in the pipeline.
Example fix
// before
services.AddAIPersistenceStores();
// after
services.AddAIPersistenceStores(options => options.UseSqlite("Data Source=elsa-ai.db")); Defensive patterns
Strategy: validation
Validate before calling
var hasOptions = services.Any(x => x.ServiceType == typeof(DbContextOptions<AIDbContext>));
if (!hasOptions)
services.AddAIPersistenceStores(o => o.UseSqlite(connectionString));
else
services.AddAIPersistenceStores(); Try / catch
try { services.AddAIPersistenceStores(); } catch (InvalidOperationException ex) when (ex.Message.Contains("AddAIPersistenceStores")) { services.AddAIPersistenceStores(o => o.UseSqlite(connectionString)); } Prevention
- Always pass a provider configuration delegate unless options are registered elsewhere.
- Register database provider configuration in a single shared setup method.
- Check module initialization order in DI composition roots.
When it happens
Trigger: Calling AddAIPersistenceStores() with no arguments when DbContextOptions<AIDbContext> was never registered (e.g. AddDbContext<AIDbContext> or AddAIPersistenceStores(s => s.UseSqlite(...)) was not called).
Common situations: Forgetting the database provider in DI setup; calling AddAIPersistenceStores before AddDbContext in a different module; copy-pasted setup that dropped the UseSqlite/UseSqlServer call.
Understand the failure class
Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.
Related errors
- Build() must be called before accessing services
- AI conversation entity metadata was not found.
- AI conversation table metadata was not found.
- Cannot overwrite an AI conversation that belongs to another…
- Failed to insert AI conversation
AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13).
Data as JSON: /api/errors/57904dd1962611be.
Report an issue: GitHub.
Appendix: source
Thrown at src/modules/Elsa.AI.Persistence.EFCore/Extensions/ServiceCollectionExtensions.cs:20
using Elsa.AI.Persistence.EFCore;
using Elsa.AI.Persistence.EFCore.Services;
using Elsa.AI.Persistence.EFCore.Stores;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
// ReSharper disable once CheckNamespace
namespace Elsa.Extensions;
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddAIPersistenceStores(this IServiceCollection services, Action<DbContextOptionsBuilder>? configureDbContext = null)
{
if (!services.Any(x => x.ServiceType == typeof(DbContextOptions<AIDbContext>)))
{
if (configureDbContext == null)
throw new InvalidOperationException($"Register {nameof(AIDbContext)} with configured {nameof(DbContextOptions<AIDbContext>)} before calling {nameof(AddAIPersistenceStores)}, or call {nameof(AddAIPersistenceStores)} with a database provider configuration.");
else
services.AddDbContext<AIDbContext>(configureDbContext);
}
services.TryAddScoped<AIDbContext>();
services.AddAIPersistenceStoreServices();
return services;
}
internal static IServiceCollection AddAIPersistenceStoreServices(this IServiceCollection services)
{
services.Replace(ServiceDescriptor.Scoped<IAIConversationStore, EFCoreAIConversationStore>());
services.Replace(ServiceDescriptor.Scoped<IAIProposalStore, EFCoreAIProposalStore>());
services.TryAddEnumerable(ServiceDescriptor.Scoped<IAIAuditEventHandler, EFCoreAIAuditSink>());
services.TryAddEnumerable(ServiceDescriptor.Singleton<IHostedService, EFCoreAIConversationCleanupService>());
return services;View on GitHub (pinned to fe9217bdfa)