abpframework/abp · error · Exception

An object accessor is registered before for type: {typeof(T)

Error message

An object accessor is registered before for type: {typeof(T).AssemblyQualifiedName}

What it means

Thrown by ServiceCollectionObjectAccessorExtensions.AddObjectAccessor<T> when an ObjectAccessor<T> (or IObjectAccessor<T>) descriptor for the same T is already in the service collection. Object accessors are meant to hold a single shared instance per type during early startup (before the provider is built), so double-registration is treated as a programming error rather than silently overwritten.

Source

Thrown at framework/src/Volo.Abp.Core/Microsoft/Extensions/DependencyInjection/ServiceCollectionObjectAccessorExtensions.cs:33

        return services.AddObjectAccessor<T>();
    }

    public static ObjectAccessor<T> AddObjectAccessor<T>(this IServiceCollection services)
    {
        return services.AddObjectAccessor(new ObjectAccessor<T>());
    }

    public static ObjectAccessor<T> AddObjectAccessor<T>(this IServiceCollection services, T obj)
    {
        return services.AddObjectAccessor(new ObjectAccessor<T>(obj));
    }

    public static ObjectAccessor<T> AddObjectAccessor<T>(this IServiceCollection services, ObjectAccessor<T> accessor)
    {
        if (services.Any(s => s.ServiceType == typeof(ObjectAccessor<T>)))
        {
            throw new Exception("An object accessor is registered before for type: " + typeof(T).AssemblyQualifiedName);
        }

        //Add to the beginning for fast retrieve
        services.Insert(0, ServiceDescriptor.Singleton(typeof(ObjectAccessor<T>), accessor));
        services.Insert(0, ServiceDescriptor.Singleton(typeof(IObjectAccessor<T>), accessor));

        return accessor;
    }

    public static T? GetObjectOrNull<T>(this IServiceCollection services)
        where T : class
    {
        return services.GetSingletonInstanceOrNull<IObjectAccessor<T>>()?.Value;
    }

    public static T GetObject<T>(this IServiceCollection services)
        where T : class
    {

View on GitHub (pinned to 7ed43b1931)

Solutions

  1. Use TryAddObjectAccessor<T>() instead, which returns the existing accessor if one is already registered rather than throwing.
  2. Remove the duplicate AddObjectAccessor call; let the earlier registration win.
  3. Identify which component already registered the accessor (search the codebase for AddObjectAccessor<T>) and avoid re-adding it.

Example fix

// before — throws if T already registered
services.AddObjectAccessor<IConfiguration>(config);

// after — idempotent
services.TryAddObjectAccessor<IConfiguration>();
// or ensure you only register once before this point
Defensive patterns

Strategy: validation

Validate before calling

// Prefer the idempotent TryAddObjectAccessor to avoid duplicate-registration exceptions
services.TryAddObjectAccessor<T>();

Prevention

When it happens

Trigger: Calling services.AddObjectAccessor<T>() twice for the same T; a module and a host configuration both registering the same accessor type (e.g. IConfiguration, IAbpHostEnvironment).

Common situations: Custom startup code that registers IConfiguration or another accessor that ABP's framework already added; calling AddObjectAccessor in a module whose dependency also adds it; integrating a library that adds an accessor ABP also manages.

Related errors


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