abpframework/abp · critical · AbpInitializationException

Services have already been configured! If you call Configure

Error message

Services have already been configured! If you call ConfigureServicesAsync method, you must have set AbpApplicationCreationOptions.SkipConfigureServices to true before.

What it means

ConfigureServices() / ConfigureServicesAsync() may run only once per AbpApplication; the private _configuredServices flag enforces this. When you create the app WITHOUT setting AbpApplicationCreationOptions.SkipConfigureServices, the constructor itself calls ConfigureServices() before returning. Calling ConfigureServicesAsync() afterward trips the guard. The flag exists so hosts that need to defer configuration (external DI, tests) can opt out and configure manually.

Source

Thrown at framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationBase.cs:306

        foreach (var module in Modules)
        {
            if (module.Instance is AbpModule abpModule)
            {
                abpModule.ServiceConfigurationContext = null!;
            }
        }

        _configuredServices = true;

        TryToSetEnvironment(Services);
    }

    private void CheckMultipleConfigureServices()
    {
        if (_configuredServices)
        {
            throw new AbpInitializationException("Services have already been configured! If you call ConfigureServicesAsync method, you must have set AbpApplicationCreationOptions.SkipConfigureServices to true before.");
        }
    }

    //TODO: We can extract a new class for this
    public virtual void ConfigureServices()
    {
        CheckMultipleConfigureServices();

        var context = new ServiceConfigurationContext(Services);
        Services.AddSingleton(context);

        foreach (var module in Modules)
        {
            if (module.Instance is AbpModule abpModule)
            {
                abpModule.ServiceConfigurationContext = context;
            }
        }

View on GitHub (pinned to 7ed43b1931)

Solutions

  1. Pass options => options.SkipConfigureServices = true when creating the app, then call ConfigureServicesAsync() yourself exactly once.
  2. Or remove the duplicate call and let the framework configure once (the default path does it in the constructor).
  3. If using AbpApplicationFactory.CreateAsync, it auto-configures - do not call ConfigureServicesAsync again on the result.

Example fix

// before
await AbpApplicationFactory.CreateAsync<MyModule>(services);
await application.ConfigureServicesAsync(); // throws

// after
await AbpApplicationFactory.CreateAsync<MyModule>(services,
    options => options.SkipConfigureServices = true);
await application.ConfigureServicesAsync();
Defensive patterns

Strategy: validation

Validate before calling

// When you need to configure manually, opt out of auto-config at creation:
var app = await AbpApplicationFactory.CreateAsync<MyModule>(services,
    options => options.SkipConfigureServices = true);
await app.ConfigureServicesAsync(); // now safe, exactly once

Prevention

When it happens

Trigger: Creating the app via a factory that auto-configures, then calling ConfigureServicesAsync() again; or calling ConfigureServices()/ConfigureServicesAsync() twice in code.

Common situations: Migrating from sync to async init and forgetting to remove the old call; a test harness that re-inits the same app; mixing AddApplicationAsync (auto-configures) with a manual ConfigureServicesAsync.

Related errors


AI-assisted analysis of abpframework/abp@7ed43b1931 (2026-08-13). Data as JSON: /api/errors/458dbb00d88dc2fe. Report an issue: GitHub.