Download

The server principal is not able to access the database under the current security context

Your login is signed in to the server but has no way into that database: there’s no database user for it, its user was orphaned by a restore, or you’re running under EXECUTE AS USER, which is confined to one database. Add or re-map the user, or change how the procedure impersonates.

SQL Server error 916· Tested on SQL Server 2022 RTM-CU27 (16.0.4295.3), and a temporary 2022 server for logins; same messages on 2019 RTM-CU32-GDR and 2025 RTM-CU9· Updated 11 October 2026

The server principal "reader" is not able to access the database "sales" under the current security context.

What it means

SQL Server checks access in two steps. Your login (the server principal) gets you onto the server; inside each database you need a user mapped to that login, or the database has to allow guest. You’re signed in, but in this database there’s no user for you, so USE, a three-part name such as sales.dbo.orders, or a procedure that reaches into that database fails:

Msg 916, Level 14, State 2, Server 7732422b7f56, Line 1
The server principal "reader" is not able to access the database "sales" under the current security context.

If you name that database when you connect instead, the sign-in itself fails, with 4060 and 18456. When the server principal in the message is a long string like S-1-9-3-1116818833-…, the statement ran under EXECUTE AS USER (cause 3 below).

Common causes

  1. The login was never given a user in that database. Creating a login doesn’t create users; each database needs its own.
  2. An orphaned user. The database was restored or attached from another server, or the login was dropped and re-created. A user is tied to its login by the login’s security identifier (SID), and a new login with the same name has a new SID, so the user app no longer belongs to the login app.
  3. Database-level impersonation. EXECUTE AS USER = …, or a procedure created WITH EXECUTE AS a user, OWNER or SELF, is trusted only inside its own database. Reaching another database from there fails with 916, even when the real login could open it.

How to fix it

Check which databases you can open

SELECT name FROM sys.databases WHERE HAS_DBACCESS(name) = 1;

Add a user for the login

Someone with ALTER ANY USER in that database (a member of db_owner or db_accessadmin) runs:

USE sales;
CREATE USER [reader] FOR LOGIN [reader];
ALTER ROLE db_datareader ADD MEMBER [reader];

Grant what the user needs: a role such as db_datareader, or GRANT SELECT ON SCHEMA::dbo and the like. Without permissions it can open the database but gets error 229 on the tables.

Re-map an orphaned user

List users whose SID matches no login:

SELECT dp.name AS orphaned_user, dp.type_desc
FROM sys.database_principals AS dp
LEFT JOIN sys.server_principals AS sp ON sp.sid = dp.sid
WHERE sp.sid IS NULL
  AND dp.type IN ('S', 'U', 'G')
  AND dp.authentication_type_desc = 'INSTANCE';

Then point each one at its login. CREATE USER would fail, since the user exists (error 15023):

ALTER USER [app] WITH LOGIN = [app];

To avoid it next time, create the login on the new server with the same SID as on the old one (CREATE LOGIN … WITH PASSWORD = …, SID = 0x…), so restored databases match it straight away.

Don’t cross databases under EXECUTE AS USER

Database-level impersonation stays in its database by design: Microsoft’s EXECUTE AS reference says any attempt to reach another database under it fails. To let a procedure read another database, sign it with a certificate and give that certificate’s user in the other database the permission it needs (Microsoft has a tutorial on signing procedures), or drop the EXECUTE AS and give the callers access themselves. Setting the database TRUSTWORTHY also lifts the limit, but it lets code in that database use its owner’s server-level rights, and Microsoft recommends leaving it off.

Reproduce it

On SQL Server 2022 (16.0.4295.3) with sqlcmd, signed in as reader, a login with a user in database inlet but none in sales:

USE sales;
SELECT TOP (1) name FROM sales.sys.tables;
Msg 916, Level 14, State 2, Server 7732422b7f56, Line 1
The server principal "reader" is not able to access the database "sales" under the current security context.
Msg 916, Level 14, State 2, Server 7732422b7f56, Line 1
The server principal "reader" is not able to access the database "sales" under the current security context.

HAS_DBACCESS('sales') returned 0 and HAS_DBACCESS('inlet') 1. As inlet, which can open sales, a procedure WITH EXECUTE AS 'seo_err_app' (a temporary user without a login) that counted sales.sys.tables, and then EXECUTE AS USER = 'inlet':

Msg 916, Level 14, State 2, Server 7732422b7f56, Procedure seo_err_mssql.sales_count, Line 2
The server principal "S-1-9-3-1116818833-1203971235-3338866075-816358699" is not able to access the database "sales" under the current security context.
Msg 916, Level 14, State 2, Server 7732422b7f56, Line 2
The server principal "inlet" is not able to access the database "sales" under the current security context.

The second fails although the inlet login itself can USE sales: impersonating its user confines it to inlet. The logins part ran on a temporary SQL Server 2022 container of our own, removed afterwards: a new login app with no user in database shop got 916; after CREATE USER app FOR LOGIN app and a GRANT, it read the table. After DROP LOGIN app and CREATE LOGIN app again, it got 916 once more, the orphan query listed app, CREATE USER failed with Msg 15023 … User, group, or role 'app' already exists in the current database., and ALTER USER app WITH LOGIN = app brought access back. SQL Server 2019 and 2025 printed the same messages for the reader and EXECUTE AS cases.

In Inlet

Inlet doesn’t manage logins and users yet, so run the CREATE USER or ALTER USER above in a query tab, signed in as someone allowed to. When SQL Server refuses, Inlet shows its message with SQL Server error 916, state 2, severity 14 and links to this page.

Inlet: a database client for the Mac

One native app for PostgreSQL, MySQL, SQL Server, SQLite, MongoDB and Redis. It explains errors where they happen, holds your edits until you save them, and keeps production read-only until you say so.

Version 0.1.0 · macOS 26 Tahoe or later · Apple silicon and Intel