- Error number
- 916
- Severity
- 14 (user-correctable error)
- State
- 1 or 2 (state 2 reproduced for an impersonated database user)
- Product
- Microsoft SQL Server Database Engine
- Versions
- All supported SQL Server versions (2016 to 2025), Azure SQL Managed Instance
- Category
- Logins & Permissions
- Last reviewed
- 23 October 2026
On this page
What it means
Error 916 means the current login (or impersonated user) tried to use a database where it has no user and the guest user has no CONNECT permission, so SQL Server refuses to let it in.
A login reaches a database through a database user mapped to it. When there is no such user, SQL Server falls back to the guest user, and only if guest has CONNECT in that database. Guest is enabled in master, msdb and tempdb but not in new user databases or model, so a three-part name such as Reporting.dbo.Sales, a USE Reporting, or a tool that lists databases fails with 916 at severity 14.
Read the two quoted names: the first is the server principal SQL Server checked (a login name, or a SID such as S-1-9-3-... when the context comes from EXECUTE AS USER for a user without a login), the second is the database it was refused. Impersonating a database user is scoped to that one database, so even a sysadmin who runs EXECUTE AS USER gets 916 when the batch reaches into another database. If the user can enter the database but lacks rights on an object, the error is 229 instead.
Common causes
- The login has no user in the target database, and guest is disabled there (the default for user databases).
- A query uses a three-part name or a
USEstatement for a database the login was never given access to. - Code running under
EXECUTE AS USER(or inside a module with an EXECUTE AS clause) references another database; the impersonated context is only valid in its own database. - CONNECT on
msdbwas revoked or denied, and SQL Server Management Studio Object Explorer queries msdb for Policy Based Management status (documented by Microsoft). - A database was restored or moved and the user for this login was not recreated or remapped there.
Diagnose it
Read-only These queries only read metadata and dynamic management views. They do not change data, permissions or configuration, so they are safe to run first.
Which databases can the current context enter?
Run this as the affected login. HAS_DBACCESS returns 1 only where the login has a user (or guest has CONNECT).
SELECT name, state_desc, HAS_DBACCESS(name) AS can_access
FROM sys.databases
ORDER BY name; 0 next to the database named in the message confirms 916: there is no usable user for this login there.
Who am I right now: login, original login and database user
SELECT SUSER_SNAME() AS current_login,
ORIGINAL_LOGIN() AS original_login,
USER_NAME() AS database_user; If current_login differs from original_login, or is a SID, the batch runs under impersonation, which explains a 916 even for an administrator.
Does guest have CONNECT in this database?
Run it in the database named in the error (as a user that can enter it).
SELECT dp.name, pe.permission_name, pe.state_desc
FROM sys.database_permissions AS pe
JOIN sys.database_principals AS dp ON dp.principal_id = pe.grantee_principal_id
WHERE dp.name = N'guest' AND pe.permission_name = N'CONNECT'; No row means guest is disabled, which is the secure default for user databases. Do not enable it to fix 916; create a user instead.
Is there a user for the login in the target database?
Run in the target database as an administrator; replace the login name.
SELECT dp.name AS user_name, dp.type_desc, sp.name AS login_name
FROM sys.database_principals AS dp
LEFT JOIN sys.server_principals AS sp ON sp.sid = dp.sid
WHERE sp.name = N'app_user' OR dp.name = N'app_user'; No row: the login needs a user here. A row with login_name NULL: an orphaned user whose SID no longer matches the login (see error 15023 for remapping).
How to fix it
Each fix is labelled with what it changes. Try read-only checks and the least invasive fix first, and test changes outside production.
Create a user for the login in the target database, with only the roles it needs
Changes permissionsThis is the normal fix. Run it in the database named in the error. Add read or write roles, or specific GRANTs, as the application requires.
-- In the target database (for example Reporting)
CREATE USER [app_user] FOR LOGIN [app_user];
ALTER ROLE db_datareader ADD MEMBER [app_user];
Remove the cross-database reference, or run it outside the impersonated context
Client or network sideIf the code does not really need the other database, use the local copy of the object. If it runs under EXECUTE AS USER, call REVERT before the cross-database part, or test with EXECUTE AS LOGIN (which carries server identity) instead of EXECUTE AS USER.
For a stored procedure that must read another database, sign it with a certificate
Changes permissionsModule signing gives one procedure the access it needs without widening anyone else's rights: create a certificate, sign the procedure, copy the certificate to the other database and create a user from it with the needed permissions. Microsoft's 916 page also lists granting CONNECT to guest and setting TRUSTWORTHY ON; avoid both, because they open the database to every login or let database owners escalate across databases.
Restore CONNECT on msdb for SQL Server Management Studio users
Changes permissionsIf the error appears in Object Explorer with Failed to retrieve data for this request and the database is msdb, someone removed CONNECT from guest or from the login in msdb. Restore it for the login concerned rather than for everyone.
USE msdb;
GRANT CONNECT TO [app_user]; -- app_user must have a user in msdb
Examples
An impersonated database user reads another database
The user has no login, so the server principal in the message is its SID (S-1-9-3-...); the number changes every time the user is created. model has guest disabled, like a new user database.
CREATE USER report_user WITHOUT LOGIN;
EXECUTE AS USER = 'report_user';
SELECT name FROM model.sys.tables; -- another database
REVERT;
Msg 916, Level 14, State 2, Line 4 The server principal "S-1-9-3-2037510283-1339403204-3953826701-2893260084" is not able to access the database "model" under the current security context.
Reproduced on SQL Server 2025 (17.0.1145.4), 23 October 2026.
The same user against msdb: guest lets it in, so the error becomes 229
msdb has guest enabled, so the impersonated user gets into the database and is stopped one step later at the object. This shows the difference between 916 (cannot enter the database) and 229 (inside, but no permission on the object).
CREATE USER report_user WITHOUT LOGIN;
EXECUTE AS USER = 'report_user';
SELECT TOP (1) name FROM msdb.dbo.sysjobs;
REVERT;
Msg 229, Level 14, State 5, Line 4 The SELECT permission was denied on the object 'sysjobs', database 'msdb', schema 'dbo'.
Reproduced on SQL Server 2025 (17.0.1145.4), 23 October 2026.
How to prevent it
Script database access together with logins: every deployment that creates a login should create its users in the databases it needs, with roles rather than direct grants. Keep guest disabled in user databases and do not rely on it for application access.
Avoid cross-database references in code that runs under impersonation; where a procedure must cross databases, use certificate signing so the access is explicit and auditable. The SQL Server security lesson covers logins, users and roles.
Common questions
Why do I get error 916 as sysadmin?
Because the batch is running under EXECUTE AS USER (or a module with EXECUTE AS). A database user context is valid only in its own database, so referencing any other database fails with 916 until you REVERT.
What is the S-1-9-3 number in the 916 message?
It is the SID of a database user created WITHOUT LOGIN. Such a user has no server principal name, so SQL Server prints the SID where a login name would normally appear.
Should I enable guest or TRUSTWORTHY to fix 916?
No. Both are listed by Microsoft as possible workarounds but widen access for every login or allow privilege escalation. Create a user for the specific login, or sign the module that needs cross-database access.
Learn more on CodeWithSQL
Official documentation
Last technically reviewed 23 October 2026; examples and diagnostics run on SQL Server 2025 (17.0.1145.4). Message text checked against the engine's sys.messages catalogue.