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

  1. Pass a provider configuration: AddAIPersistenceStores(o => o.UseSqlite(connectionString)).
  2. Register options first via AddDbContext<AIDbContext>(...) before calling AddAIPersistenceStores().
  3. 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

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


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)