abpframework/abp · error · AbpException
serviceKey can not be null! Use ExposeServicesAttribute inst
Error message
serviceKey can not be null! Use ExposeServicesAttribute instead.
What it means
Thrown by the ExposeKeyedServiceAttribute<TServiceType> constructor (generic form) when the serviceKey argument is null. ABP tells you to use ExposeServicesAttribute instead, because a null key has no meaning for keyed service registration. It is an AbpException.
Source
Thrown at framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ExposeKeyedServiceAttribute.cs:15
using System;
namespace Volo.Abp.DependencyInjection;
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class ExposeKeyedServiceAttribute<TServiceType> : Attribute, IExposedKeyedServiceTypesProvider
where TServiceType : class
{
public ServiceIdentifier ServiceIdentifier { get; }
public ExposeKeyedServiceAttribute(object serviceKey)
{
if (serviceKey == null)
{
throw new AbpException($"{nameof(serviceKey)} can not be null! Use {nameof(ExposeServicesAttribute)} instead.");
}
ServiceIdentifier = new ServiceIdentifier(serviceKey, typeof(TServiceType));
}
public ServiceIdentifier[] GetExposedServiceTypes(Type targetType)
{
return new[] { ServiceIdentifier };
}
}
View on GitHub (pinned to 7ed43b1931)
Solutions
- Pass a concrete non-null key (a string, enum, or object) to the attribute.
- If you do not need keying at all, switch to [ExposeServices(typeof(TService))].
- If the key comes from a constant, ensure the constant is initialized and non-null.
Example fix
// before
[ExposeKeyedServiceAttribute<IMyService>(null)]
public class MyService : IMyService { }
// after
[ExposeKeyedServiceAttribute<IMyService>("primary")]
public class MyService : IMyService { } Defensive patterns
Strategy: validation
Validate before calling
// Attributes are compile-time; 'validate' by never passing null. // Use a real key literal or switch to ExposeServicesAttribute.
Try / catch
try { /* attribute ctor runs at reflection time */ }
catch (AbpException ex) when (ex.Message.Contains("serviceKey"))
{
logger.LogError(ex, "Keyed service attribute misconfigured on {Type}", type);
} Prevention
- Always pass a concrete key (string/enum/object) to ExposeKeyedServiceAttribute.
- If you do not need keying, use [ExposeServices(typeof(T))] instead.
- Avoid [ExposeKeyedServiceAttribute<T>(someField)] where someField could be null.
When it happens
Trigger: Decorating a class with [ExposeKeyedServiceAttribute<TService>(null)] or passing a null-typed constant/field as serviceKey at the attribute level.
Common situations: Mistakenly passing null (or an uninitialized static field) as the keyed-service key, or confusing the keyed attribute with the non-keyed ExposeServicesAttribute.
Related errors
- Could not find singleton service: {typeof(T).AssemblyQualifi
- Could not find {typeof(IServiceProviderFactory<TContainerBui
- Could not find an implementation of {typeof(IConfiguration).
- An object accessor is registered before for type: {typeof(T)
- Could not find an object of {typeof(T).AssemblyQualifiedName
AI-assisted analysis of abpframework/abp@7ed43b1931 (2026-08-13).
Data as JSON: /api/errors/48250e2736f51217.
Report an issue: GitHub.