aspnetboilerplate/aspnetboilerplate · error · AbpException
Session.TenantId is null! Possible problems: No user logged…
Error message
Session.TenantId is null! Possible problems: No user logged in or current logged in user in a host user (TenantId is always null for host users).
What it means
AbpSessionExtensions.GetTenantId() is a convenience extension that returns the current tenant Id as a non-nullable int. ABP throws this AbpException because TenantId is nullable (int?) and is null both when no user is logged in and when the current user is the host (tenant-less) user, for which a tenant Id has no meaning. The library refuses to guess a default (like 0 or 1) so callers must explicitly handle the null case.
Solutions
- Check session.TenantId.HasValue before calling GetTenantId and branch on the null case
- Use session.GetTenantId() only after authenticating the user, or use session.GetUserId()/GetMultiTenancySideCode appropriately
- In background jobs, inject and call IAbpSession.Use(tenantId, userId) scope to supply the tenant context
- In tests, wrap calls in a session 'Use' scope or mock IAbpSession with TenantId set
Example fix
// before
int tenantId = _abpSession.GetTenantId();
// after
if (_abpSession.TenantId.HasValue)
{
int tenantId = _abpSession.GetTenantId();
// ...
}
else
{
// handle anonymous or host-user context
} Defensive patterns
Strategy: type-guard
Validate before calling
if (session.TenantId.HasValue) { var tenantId = session.GetTenantId(); } Type guard
bool hasTenant = session is IAbpSession s && s.TenantId.HasValue;
Try / catch
try { tenantId = session.GetTenantId(); } catch (AbpException) { /* anonymous/host context: use default or skip */ } Prevention
- Check TenantId.HasValue before calling Get* extensions
- Use IAbpSession.Use(tenantId, userId) scopes in background jobs and tests
- Never assume a tenant context in host-side or anonymous code paths
When it happens
Trigger: Calling session.GetTenantId() when session.TenantId is null: (1) before a user logs in, (2) from code executing on the host side (no tenant), (3) in a background job/thread where IAbpSession is not populated (no ambient user context), (4) in unit tests with a stub session that has no TenantId set.
Common situations: Application services called by anonymous users; code scheduled via background workers or Hangfire without session override; multi-tenant apps where an admin operating at host level invokes tenant-specific logic; tests using NullAbpSession or DefaultSession without Use(tenantId, userId).
Related errors
- FeatureChecker can not get a feature value by name…
- ArgumentNullException
- Can not delete a host language from tenant!
- Can not insert null values to the cache!
- Can not set TenantId to 0 for IMustHaveTenant entities!
AI-assisted analysis of aspnetboilerplate/aspnetboilerplate@2323c13a15 (2026-09-08).
Data as JSON: /api/errors/7a802643461e7f2d.
Report an issue: GitHub.
Appendix: source
Thrown at src/Abp/Runtime/Session/AbpSessionExtensions.cs:35
{
throw new AbpException("Session.UserId is null! Probably, user is not logged in.");
}
return session.UserId.Value;
}
/// <summary>
/// Gets current Tenant's Id.
/// Throws <see cref="AbpException"/> if <see cref="IAbpSession.TenantId"/> is null.
/// </summary>
/// <param name="session">Session object.</param>
/// <returns>Current Tenant's Id.</returns>
/// <exception cref="AbpException"></exception>
public static int GetTenantId(this IAbpSession session)
{
if (!session.TenantId.HasValue)
{
throw new AbpException("Session.TenantId is null! Possible problems: No user logged in or current logged in user in a host user (TenantId is always null for host users).");
}
return session.TenantId.Value;
}
/// <summary>
/// Creates <see cref="UserIdentifier"/> from given session.
/// Returns null if <see cref="IAbpSession.UserId"/> is null.
/// </summary>
/// <param name="session">The session.</param>
public static UserIdentifier ToUserIdentifier(this IAbpSession session)
{
return session.UserId == null
? null
: new UserIdentifier(session.TenantId, session.GetUserId());
}
}
}View on GitHub (pinned to 2323c13a15)