SQL Server error 18456 — login failed for user
The client message deliberately says nothing useful. The SQL error log records a state number that says exactly what was wrong.
What you see
Applications fail to connect with "Login failed for user". The client always shows State 1, which means nothing — the real state is only in the server's log.
What is actually wrong
Depends on the state: 5 is an unknown login, 8 is a wrong password, 38 is a missing or inaccessible database, 40 cannot open the default database, 11 and 12 are a valid Windows login with no SQL access.
Codes and articles
Fixes (2)
Read the state, then fix the login
Any 18456. Always read the state first — it turns this from guesswork into one action.
Read the server's own error log, which is the only place the real state appears.
EXEC xp_readerrorlog 0, 1, N'Login failed';The client is told State 1 on purpose, so an attacker cannot tell 'no such user' from 'wrong password'. The server log has no such restriction.
Confirm the server accepts SQL logins at all. Mode 1 is Windows-only, 2 is mixed.
SELECT SERVERPROPERTY('IsIntegratedSecurityOnly') AS WindowsAuthOnly;If it is Windows-only and you need a SQL login, switch to mixed mode — this needs a service restart.
EXEC xp_instance_regwrite N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'LoginMode', REG_DWORD, 2;Check the login exists and is not disabled or locked out.
SELECT name, is_disabled, LOGINPROPERTY(name,'IsLocked') AS IsLocked, LOGINPROPERTY(name,'IsExpired') AS IsExpired FROM sys.server_principals WHERE type IN ('S','U','G');Enable and unlock as needed.
ALTER LOGIN [appuser] ENABLE;ALTER LOGIN [appuser] WITH PASSWORD = 'NewStrongPassword' UNLOCK;
For state 11 or 12, the Windows account authenticated but has no SQL login — create one.
CREATE LOGIN [EXAMPLE\AppService] FROM WINDOWS;
EXEC xp_readerrorlog 0, 1, N'Login succeeded';Fix the default database problem
State 38 or 40 — the login is fine but the database it wants is not.
Find which database is being asked for.
EXEC xp_readerrorlog 0, 1, N'Login failed', N'38';Check the database exists and is online.
SELECT name, state_desc, user_access_desc, is_read_only FROM sys.databases ORDER BY name;Bring it online if it is not.
ALTER DATABASE [AppDb] SET ONLINE;ALTER DATABASE [AppDb] SET MULTI_USER;
Check the login's default database — a login pointing at a database that has been dropped fails before it can connect anywhere.
SELECT name, default_database_name FROM sys.server_principals WHERE type IN ('S','U');Point it somewhere that exists.
ALTER LOGIN [appuser] WITH DEFAULT_DATABASE = [master];Map the login to a user in the database if it is not already.
USE [AppDb];CREATE USER [appuser] FOR LOGIN [appuser];ALTER ROLE db_datareader ADD MEMBER [appuser];
SELECT DB_NAME() AS CurrentDb, SUSER_NAME() AS LoginName;Related faults
Where this stops. This write-up was written and checked by hand. It says what each step changes, how to confirm it worked and how to reverse it, and anything destructive is flagged before you reach it. If it does not match what your machine is doing, search the Support Centre for the exact code or message — and when something needs a person, get in touch.