GRANT VIEW SERVER STATE TO [login]; It is read-only and safe. If the grant appears to do nothing, look for a DENY, which always wins.
You hit this the moment you try to look at what the server is doing rather than what it holds. Every interesting DMV, running requests, waits, connections, query plans, memory, is gated behind VIEW SERVER STATE.
The reason it surprises people is that db_datareader, db_owner, even full control of a database, grant none of it. Server state is a server-level permission and database roles cannot reach it.
Confirm What You Actually Have
-- What am I, and what am I allowed to do at server level?
SELECT SUSER_NAME() AS login_name,
IS_SRVROLEMEMBER('sysadmin') AS is_sysadmin,
HAS_PERMS_BY_NAME(NULL, NULL, 'VIEW SERVER STATE') AS has_view_server_state,
HAS_PERMS_BY_NAME(NULL, NULL, 'VIEW ANY DEFINITION') AS has_view_any_definition;
has_view_server_state returning 0 is your answer.
To see it for someone else, read the grant directly:
SELECT pr.name AS principal_name,
pr.type_desc,
pe.permission_name,
pe.state_desc -- GRANT, DENY, GRANT_WITH_GRANT_OPTION
FROM sys.server_permissions pe
JOIN sys.server_principals pr ON pr.principal_id = pe.grantee_principal_id
WHERE pe.permission_name = 'VIEW SERVER STATE'
ORDER BY pr.name;
The Fix
GRANT VIEW SERVER STATE TO [DOMAIN\your_login];
That is it, and it is genuinely safe to grant. VIEW SERVER STATE is read-only. It exposes what the server is doing, sessions, waits, query text, plans, and grants no ability to change anything, read user data, or alter security.
For a monitoring account, this is usually the right minimum set:
GRANT VIEW SERVER STATE TO [DOMAIN\monitoring_account]; -- DMVs
GRANT VIEW ANY DEFINITION TO [DOMAIN\monitoring_account]; -- object definitions
GRANT CONNECT SQL TO [DOMAIN\monitoring_account];
Do not solve this with sysadmin. It is the reflex, it works, and it hands over the entire instance to something that only needed to read a DMV.
On SQL Server 2022 and later the message may not say VIEW SERVER STATE at all. Querying sys.dm_os_wait_stats without the grant returns Msg 300 naming VIEW SERVER PERFORMANCE STATE, and the security DMVs name VIEW SERVER SECURITY STATE. Those are the two narrower permissions SQL Server 2022 added underneath VIEW SERVER STATE. Granting VIEW SERVER STATE still covers both, and a monitoring login that only reads performance DMVs can be given the performance one on its own. Measured on SQL Server 2025 with a login holding neither.
Microsoft’s reference covers GRANT Server Permissions in full, including which of the 2022 permissions sits under which.
The One That Catches Everyone: DENY
If a GRANT appears to do nothing, look for a DENY, including one inherited from a Windows group the login belongs to. DENY always beats GRANT, no matter which is more specific or which came last.
-- Any DENY that could be overriding the grant, direct or via a group
SELECT pr.name AS principal_name, pr.type_desc, pe.permission_name, pe.state_desc
FROM sys.server_permissions pe
JOIN sys.server_principals pr ON pr.principal_id = pe.grantee_principal_id
WHERE pe.state_desc = 'DENY'
AND pe.permission_name IN ('VIEW SERVER STATE', 'CONNECT SQL');
Remove it rather than layering another grant on top:
REVOKE VIEW SERVER STATE FROM [DOMAIN\the_group];
GRANT VIEW SERVER STATE TO [DOMAIN\your_login];
Partial Results Instead of an Error
A subtler version: the query runs, returns rows, and quietly shows you only your own sessions. Several DMVs behave that way, with VIEW SERVER STATE you see the whole instance, without it you see yourself.
If sys.dm_exec_requests shows 1 row and you were expecting a busy server, you are looking at a permissions problem, not an idle instance. That one has cost me real time.
Measured on SQL Server 2025 CU8, same instance, 2 logins: without the grant sys.dm_exec_requests returned 1 row and sys.dm_exec_sessions 1 row. With VIEW SERVER STATE granted, the same 2 queries returned 86 and 93. No error either way.
Azure SQL Database Is Different
There is no server-level VIEW SERVER STATE in Azure SQL Database. The equivalent is granted inside the database:
GRANT VIEW DATABASE STATE TO [your_user];
Managed Instance behaves like the boxed product and uses VIEW SERVER STATE.
Stopping It Recurring
- Grant to a group, not a person. The recurring version of this incident is a new starter, or somebody’s account being recreated, and the individual grant not existing.
- Give monitoring tools their own login with the three grants above. Shared accounts are how
sysadmincreeps in. - Audit for
DENYafter any security review. Hardening passes add denies that surface weeks later as this error.
Common Questions
Is VIEW SERVER STATE safe to grant?
I granted it and nothing changed.
The DMV returns 1 row instead of the whole instance.
The message says VIEW SERVER PERFORMANCE STATE, not VIEW SERVER STATE. Which do I grant?
VIEW SERVER STATE into two narrower children, VIEW SERVER PERFORMANCE STATE for the performance DMVs and VIEW SERVER SECURITY STATE for the security ones, and the denial now names the one the DMV needs. GRANT VIEW SERVER STATE covers both; grant the narrower one when the login genuinely only needs that half.VIEW SERVER STATE is the permission most monitoring scripts need. Once it is granted, these are what you run.
- Login Failed or Permission Denied, the router for when the denial is not VIEW SERVER STATE
- Get Permissions and Role Membership, one login’s effective access across the instance, including this grant.
- Get Sysadmin Members, who holds the keys, and the reason not to add another one.
- Get Wait Statistics, one of the many things this permission unlocks.
- SQL Server Security Scripts, permissions, logins and role membership auditing.
- DBA Scripts, the full script library, most of which needs this permission.
Leave a Reply