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

  1. Check session.TenantId.HasValue before calling GetTenantId and branch on the null case
  2. Use session.GetTenantId() only after authenticating the user, or use session.GetUserId()/GetMultiTenancySideCode appropriately
  3. In background jobs, inject and call IAbpSession.Use(tenantId, userId) scope to supply the tenant context
  4. 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

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


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)