What it means
A security statement named a principal (a user, login or role) or a schema that SQL Server couldn’t act on. Either it doesn’t exist where SQL Server looked, or you don’t have the permission to see or change it. The message doesn’t say which, so that it can’t be used to discover names you aren’t allowed to see:
Msg 15151, Level 16, State 1, Server 7732422b7f56, Line 1
Cannot find the user 'seo_err_nobody', because it does not exist or you do not have permission.
The verb depends on the statement: Cannot find the user (GRANT … TO), Cannot add the principal
(ALTER ROLE … ADD MEMBER), Cannot alter the login (ALTER LOGIN), Cannot drop the user, the login, the role or the schema (DROP …).
Logins and users are different things. A login lets you sign in to the server; a user lives
inside one database and is mapped to a login. GRANT, DENY, ALTER ROLE and DROP USER look for
users in the current database; ALTER LOGIN and DROP LOGIN look for logins on the server.
Common causes
- Granting to a login that has no user in this database. The login
appexists, but nobody ranCREATE USER appin this database, soGRANT SELECT … TO appcan’t find a user calledapp. - The wrong database. Users are per database; the script ran in
masteror another default. - The user has another name than the login, say
app_userfor the loginapp. - No permission over logins.
ALTER LOGINandDROP LOGINneedALTER ANY LOGIN(thesecurityadminrole) orCONTROL SERVER. A login without them getsCannot alter the login 'sa'…when trying to enable or resetsa, even thoughsaexists. - Already dropped: a cleanup script run twice.
CREATE USER … FOR LOGIN with a login that doesn’t exist (or that you can’t see) is error 15007:
'<name>' is not a valid login or you do not have permission.
How to fix it
Check what exists, where you are
SELECT DB_NAME() AS current_database;
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 dp.type IN ('S', 'U', 'G', 'E', 'X', 'R')
ORDER BY dp.name;
The second query lists the database’s users and roles with the login each user belongs to. Without
VIEW ANY DEFINITION or a similar permission, sys.server_principals shows you only your own login,
sa and the server roles, so a missing row there doesn’t prove a login doesn’t exist.
Create the user, then grant
USE sales;
CREATE USER [app] FOR LOGIN [app];
ALTER ROLE db_datareader ADD MEMBER [app];
GRANT EXECUTE ON SCHEMA::dbo TO [app];
This needs ALTER ANY USER in the database (db_owner or db_accessadmin). If the user already
exists but belongs to no login (after a restore from another server), CREATE USER fails with 15023;
re-map it with ALTER USER [app] WITH LOGIN = [app] instead, as described under
error 916.
Ask for login permissions, or have an administrator run it
Changing logins (passwords, enabling sa, dropping) is for members of securityadmin or sysadmin.
On Azure SQL Database, logins are managed in the master database by the server admin.
Make cleanup scripts safe to re-run
DROP USER IF EXISTS [app];
DROP ROLE IF EXISTS [reporting];
DROP SCHEMA IF EXISTS [staging];
These need SQL Server 2016 or later. DROP LOGIN has no IF EXISTS; check
SUSER_ID(N'app') IS NOT NULL first.
Reproduce it
On SQL Server 2022 (16.0.4295.3) with sqlcmd, in database inlet, as a database owner, each
statement in its own batch:
GRANT SELECT ON SCHEMA::seo_err_mssql TO seo_err_nobody;
ALTER ROLE db_datareader ADD MEMBER seo_err_nobody;
DROP USER seo_err_nobody;
DROP SCHEMA seo_err_noschema;
CREATE USER seo_err_user2 FOR LOGIN seo_err_nologin;
Msg 15151, Level 16, State 1, Server 7732422b7f56, Line 1
Cannot find the user 'seo_err_nobody', because it does not exist or you do not have permission.
Msg 15151, Level 16, State 1, Server 7732422b7f56, Line 1
Cannot add the principal 'seo_err_nobody', because it does not exist or you do not have permission.
Msg 15151, Level 16, State 1, Server 7732422b7f56, Line 1
Cannot drop the user 'seo_err_nobody', because it does not exist or you do not have permission.
Msg 15151, Level 16, State 1, Server 7732422b7f56, Line 1
Cannot drop the schema 'seo_err_noschema', because it does not exist or you do not have permission.
Msg 15007, Level 16, State 1, Server 7732422b7f56, Line 1
'seo_err_nologin' is not a valid login or you do not have permission.
DROP ROLE, ALTER ROLE … ADD MEMBER on a missing role, DROP CERTIFICATE and
GRANT SELECT ON OBJECT:: a missing table gave 15151 too, as Cannot drop the role, Cannot alter the role, Cannot drop the certificate and Cannot find the object. The login cases ran on a
temporary SQL Server 2022 container of our own, removed afterwards. There, GRANT SELECT ON dbo.events TO app before app had a user in the database gave Cannot find the user 'app', and
worked after CREATE USER app FOR LOGIN app. Signed in as app, which has no server permissions:
Msg 15151, Level 16, State 1, Server 54e64f9ad96b, Line 1
Cannot alter the login 'sa', because it does not exist or you do not have permission.
Msg 15151, Level 16, State 1, Server 54e64f9ad96b, Line 1
Cannot drop the login 'app', because it does not exist or you do not have permission.
That was ALTER LOGIN sa ENABLE, then DROP LOGIN app (its own login). sa was unchanged, and
in app’s view of sys.server_principals the only logins were app and sa. DROP LOGIN IF EXISTS
failed with a syntax error (156 near 'IF'). SQL Server 2019 and 2025 printed the same messages for
the database-level cases.
In Inlet
Inlet doesn’t manage logins and users yet, so run these statements in a query tab, signed in as
someone allowed to. When SQL Server refuses, Inlet shows its message with
SQL Server error 15151, state 1, severity 16 and links to this page.