Back to Article List

Fix SQL Server error 18456 login failed for user

Fix SQL Server error 18456 login failed for user - Fix SQL Server error 18456 login failed for user

Updated and tested 16 October 2026

The API went down and the only thing its logger produced was Login failed for user 'apiuser'. (Microsoft SQL Server, Error: 18456). That message names the user and the error number, and that is the whole of it. Your client library isn't withholding that detail. SQL Server never sent it, and that one design decision is why every 18456 investigation starts in the same place: the server error log.

MSSQL error 18456 covers an enormous range of failures. The login failed for user SQL Server writes to the client is the same string for a wrong password, a disabled login, an offline database, the wrong authentication mode, a Microsoft Entra token that didn't validate or an empty user name from a misconfigured connection pool. Roughly two dozen documented states sit behind that one message, so guessing during an outage is wasted time. Get the state, then fix the thing the state names.

SQL Server error 18456 login failed for user, client side and server side

The client side of the failure is this, in full:

Login failed for user 'apiuser'. (Microsoft SQL Server, Error: 18456)

Expand the detail in SSMS and you pick up one extra token, State: 1. That value is a decoy. State 1 is what the engine reports to every client on every authentication failure regardless of the real cause, and Microsoft's reference page for MSSQLSERVER_18456 says so outright: "To increase security, the error message that is returned to the client deliberately hides the nature of the authentication error."

On the server the same failure is written as a pair of lines, and the second one carries the client IP so you can tell which machine tried:

2007-12-05 20:12:56.34 | Logon | Error: 18456, Severity: 14, State: 8.
2007-12-05 20:12:56.34 | Logon | Login failed for user '<user_name>'. [CLIENT: <ip address>]

State 8 there is a bad password. Severity 14 never changes for this error, so ignore it. The state number is the entire payload of the message, and everything below depends on having read it.

Find the SQL Server error log

Error log path on Linux

The Database Engine writes to /var/opt/mssql/log/errorlog, and the directory is root-only, so you need sudo even to list it:

sudo cat /var/opt/mssql/log/errorlog

If that comes back as spaced-out garbage with a null byte between every character, the file is UTF-16LE and your terminal is reading it as UTF-8. Don't fight it. Convert a copy:

sudo iconv -f UTF-16LE -t UTF-8 /var/opt/mssql/log/errorlog -o /tmp/errorlog.txt
grep -a "Error: 18456" /tmp/errorlog.txt | tail -20

On any box where I've done an SQL Server install on Ubuntu, that grep sits in my shell history. The last twenty failures are almost always enough to see a pattern.

Error log path on Windows

On Windows the log lives under the instance directory, and the number in the folder name tracks the major version:

C:\Program Files\Microsoft SQL Server\MSSQL17.MSSQLSERVER\MSSQL\Log\ERRORLOG

MSSQL17 is SQL Server 2025, MSSQL16 is 2022, MSSQL15 is 2019, MSSQL14 is 2017. For a named instance the second half of the folder name carries the instance name, so a default SQLEXPRESS install on 2022 lands at MSSQL16.SQLEXPRESS. Open ERRORLOG with any editor that handles Unicode. It has no extension, and the archived copies are ERRORLOG.1 through ERRORLOG.6.

Six archives is the default and a new log opens on every service restart, which means a box that has been up for a year keeps the whole year in one enormous file. Nobody I have asked knows why six. I have never changed it. If you would rather stay in a GUI, the same file shows up under Management, SQL Server Logs, once the console is pointed at the instance (SQL Server Management Studio setup guide).

Error 18456 state codes

These are the states Microsoft documents. Anything outside the list is, in the reference page's own words, "an unexpected internal processing error", which in practice means open a support case or start reading the log around the failure for context.

States 2 and 5: The user ID isn't valid

No login by that name exists on the instance. The two states mean the same thing and the split between them is historical. Look for a domain prefix that shouldn't be there, a trailing space picked up from a config file or a login that exists on your staging server and was never scripted out to production.

States 6, 58 and 62: Windows and SQL authentication are crossed

State 6 means a Windows login name was passed on a SQL Server Authentication connection. State 58 means the server is set to Windows Authentication only and a client tried SQL authentication, or that SIDs don't match. State 62 is a Windows account hitting a contained database where the SIDs don't line up. All three are the same class of problem. On Windows the fix is usually mixed mode.

Check which mode you're in before changing anything:

SELECT SERVERPROPERTY('IsIntegratedSecurityOnly') AS IsWindowsAuthOnly;

1 means Windows Authentication only. 0 means both modes are accepted.

States 7, 8 and 9: Password problems, and a disabled login

State 8 is a wrong password. State 9 means the password isn't valid. State 7 means the login is disabled and the password is incorrect, so re-enabling the login on its own won't get you in.

State 18: The password must be changed

The login was created or altered with MUST_CHANGE, or password expiration caught up with it. Some client drivers can prompt for a new password, most can't and a connection pool never will. Reset it from another session with ALTER LOGIN.

States 11 and 12: Login valid, server access failed

Both states mean the credentials were fine and the engine then refused the session. The common case is a Windows user who is a sysadmin only through membership of the local Administrators group, on a box where UAC isn't elevating the client. There's a section on that further down.

States 38, 46 and 126: The database can't be found

States 38 and 46 mean the database requested by the user couldn't be found. State 126 means it doesn't exist. In practice this is nearly always a login whose default database has been dropped, renamed, taken offline for a restore or set to a database the login has no user in. Fix the login. On some drivers a connection string that names a database explicitly still fails when the default database is unreachable.

An older Microsoft blog, now in the Learn archive, also documents state 40 as "Failed to open the database specified in the login properties". It isn't on the current reference page, so treat it as archived guidance. The fix is identical to states 38 and 46.

States 102 to 111 and 132 to 133: Microsoft Entra failures

These are token and directory failures, so nothing you do with ALTER LOGIN will help. Look at the identity provider side: token lifetime, tenant, conditional access, the authentication mode your driver negotiated. I have only ever chased one of these as far as the token lifetime, so take the rest of that list as what the documentation says and not as something I have watched fail.

States 122 to 124: Empty user name or password

An empty credential reached the server. Print the string your app builds at runtime with the password masked, because the bug is almost always in how the MSSQL connection string gets assembled and not in what someone typed. I have seen this once from a human and dozens of times from an application that read a blank environment variable and connected anyway.

State 1 and undocumented states

State 1 in the server log (not the client message) means the error information isn't available, usually because the account reading the detail lacks permission. Other numbers show up occasionally. State 142 circulates on forums with several contradictory explanations attached, none of them documented by Microsoft.

Switch to mixed mode authentication on Windows

If the log gave you state 58 and you need SQL logins to work, the instance is running in Windows Authentication mode and has to be changed. In SSMS, right-click the server in Object Explorer, open Properties, go to the Security page and pick SQL Server and Windows Authentication mode. The equivalent from T-SQL writes the registry value directly:

EXECUTE xp_instance_regwrite N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'LoginMode', REG_DWORD, 2;

LoginMode 2 is mixed, 1 is Windows only. Both routes need a service restart before anything changes. The setting is read at startup, so until net stop MSSQLSERVER and net start MSSQLSERVER have run you keep getting state 58 against a server that looks correctly configured in the GUI. Both paths sit on Microsoft's page for changing the server authentication mode.

Enable the sa login and reset its password

A SQL Server sa login failed on a fresh Windows box usually means sa was never enabled at all. Installing in Windows Authentication mode leaves it disabled, and turning mixed mode on later doesn't enable it for you. Two statements, in this order:

USE [master];
GO
ALTER LOGIN sa ENABLE;
GO
ALTER LOGIN sa WITH PASSWORD = '<enterStrongPasswordHere>';
GO

The password policy is inherited from Windows on Windows hosts: at least eight characters, drawing on three of the four sets (uppercase, lowercase, base-10 digits, symbols), up to 128 characters. A server with remote connections enabled on SQL Server starts seeing sa attempts soon after going live, because sa is the one login name every scanner on the internet tries. Get an application off it as soon as you can, then disable it again.

Unlock a login and clear an expired password

Repeated bad passwords against a login with CHECK_POLICY on will trip the Windows account lockout policy, and the login stays locked until you clear it. If you know the new password:

ALTER LOGIN [Mary5] WITH PASSWORD = '<enterStrongPasswordHere>' UNLOCK;
GO

If you want to unlock without touching the password, toggle the policy off and back on. It looks like a hack and it's the documented method:

ALTER LOGIN [Mary5] WITH CHECK_POLICY = OFF;
ALTER LOGIN [Mary5] WITH CHECK_POLICY = ON;
GO

CHECK_POLICY defaults to ON and CHECK_EXPIRATION defaults to OFF, which surprises people who assume expiry is on by default. For a service account that must never expire mid-deployment, set CHECK_EXPIRATION = OFF explicitly and rotate the password on your own schedule.

Set a default database the login can open

States 38, 46 and 126 usually resolve to a login pointed at a database that has gone. Repoint it at something that will always be there:

ALTER LOGIN [apiuser] WITH DEFAULT_DATABASE = [master];
GO

Then work out why the real database is unavailable. SELECT name, state_desc, user_access_desc FROM sys.databases; answers that in one line: ONLINE and MULTI_USER is healthy, RESTORING or OFFLINE or SINGLE_USER is your problem.

Create a login and map it to a database user

The fix I see done badly most often is granting sysadmin because the mapping is fiddly. Don't. A login is a server-level principal, a user is a database-level principal, and you need both:

USE [master];
GO
CREATE LOGIN [apiuser] WITH PASSWORD = '<enterStrongPasswordHere>', DEFAULT_DATABASE = [orders];
GO
USE [orders];
GO
CREATE USER [apiuser] FOR LOGIN [apiuser];
GO
ALTER ROLE db_datareader ADD MEMBER [apiuser];
ALTER ROLE db_datawriter ADD MEMBER [apiuser];
GO

Skip the CREATE USER step and the login authenticates fine, then fails the moment it touches a table. That's error 916, filed with the other messages that look like 18456 and aren't on the SQL Server troubleshooting cheat sheet. It is also why people wrongly conclude their 18456 fix didn't work.

Your idea deserves better hosting

24/7 support 30-day money-back guaranteeRefund covers the VPS plan on your first order. Cancel anytime
Billing Cycle

VPS.S1

£4.49 Save  17 %
£3.74 Monthly
  • 2 vCPU AMD EPYC
  • 2 GB RAMMEMORY
  • 30 GB NVMeSTORAGE
  • Unmetered bandwidth
  • IPv4 & IPv6IPv6 is currently unavailable in France, Finland or the Netherlands. included

VPS.S3

£11.24 Save  33 %
£7.49 Monthly
  • 4 vCPU AMD EPYC
  • 6 GB RAMMEMORY
  • 70 GB NVMeSTORAGE
  • Unmetered bandwidth
  • IPv4 & IPv6IPv6 is currently unavailable in France, Finland or the Netherlands. included

VPS.S4

£14.99 Save  20 %
£11.99 Monthly
  • 6 vCPU AMD EPYC
  • 8 GB RAMMEMORY
  • 80 GB NVMeSTORAGE
  • Unmetered bandwidth
  • IPv4 & IPv6IPv6 is currently unavailable in France, Finland or the Netherlands. included

EPYC VPS.P1

£6.74 Save  22 %
£5.24 Monthly
  • 2 vCPU AMD EPYC
  • 4 GB RAMMEMORY
  • 40 GB NVMeSTORAGE
  • Unmetered bandwidth
  • IPv4 & IPv6IPv6 is currently unavailable in France, Finland or the Netherlands. included
  • Free auto backupsIncludes one backup slot you can set to run daily, weekly or monthly.

EPYC VPS.P2

£12.74 Save  24 %
£9.74 Monthly
  • 2 vCPU AMD EPYC
  • 8 GB RAMMEMORY
  • 80 GB NVMeSTORAGE
  • Unmetered bandwidth
  • IPv4 & IPv6IPv6 is currently unavailable in France, Finland or the Netherlands. included
  • Free auto backupsIncludes one backup slot you can set to run daily, weekly or monthly.

EPYC VPS.P4

£22.49 Save  23 %
£17.24 Monthly
  • 4 vCPU AMD EPYC
  • 16 GB RAMMEMORY
  • 160 GB NVMeSTORAGE
  • Unmetered bandwidth
  • IPv4 & IPv6IPv6 is currently unavailable in France, Finland or the Netherlands. included
  • Free auto backupsIncludes one backup slot you can set to run daily, weekly or monthly.

EPYC VPS.P5

£29.99 Save  25 %
£22.49 Monthly
  • 8 vCPU AMD EPYC
  • 16 GB RAMMEMORY
  • 180 GB NVMeSTORAGE
  • Unmetered bandwidth
  • IPv4 & IPv6IPv6 is currently unavailable in France, Finland or the Netherlands. included
  • Free auto backupsIncludes one backup slot you can set to run daily, weekly or monthly.

EPYC VPS.P6

£44.99 Save  25 %
£33.74 Monthly
  • 8 vCPU AMD EPYC
  • 32 GB RAMMEMORY
  • 200 GB NVMeSTORAGE
  • Unmetered bandwidth
  • IPv4 & IPv6IPv6 is currently unavailable in France, Finland or the Netherlands. included
  • Free auto backupsIncludes one backup slot you can set to run daily, weekly or monthly.

EPYC VPS.P7

£52.48 Save  29 %
£37.49 Monthly
  • 16 vCPU AMD EPYC
  • 32 GB RAMMEMORY
  • 240 GB NVMeSTORAGE
  • Unmetered bandwidth
  • IPv4 & IPv6IPv6 is currently unavailable in France, Finland or the Netherlands. included
  • Free auto backupsIncludes one backup slot you can set to run daily, weekly or monthly.

Genoa VPS.G2

£18.74 Save  20 %
£14.99 Monthly
  • 2 vCPUAMD EPYC Genoa 4th generation 9xx4 with 3.25 GHz or similar, on Zen 4 architecture. AMD EPYC G4
  • 4 GB DDR5MEMORY
  • 50 GB NVMeSTORAGE
  • Unmetered bandwidth
  • IPv4 & IPv6IPv6 is currently unavailable in France, Finland or the Netherlands. included
  • Free auto backupsIncludes one backup slot you can set to run daily, weekly or monthly.

Genoa VPS.G4

£33.74 Save  22 %
£26.24 Monthly
  • 4 vCPUAMD EPYC Genoa 4th generation 9xx4 with 3.25 GHz or similar, on Zen 4 architecture. AMD EPYC G4
  • 8 GB DDR5MEMORY
  • 100 GB NVMeSTORAGE
  • Unmetered bandwidth
  • IPv4 & IPv6IPv6 is currently unavailable in France, Finland or the Netherlands. included
  • Free auto backupsIncludes one backup slot you can set to run daily, weekly or monthly.

Genoa VPS.G6

£67.48 Save  22 %
£52.49 Monthly
  • 8 vCPUAMD EPYC Genoa 4th generation 9xx4 with 3.25 GHz or similar, on Zen 4 architecture. AMD EPYC G4
  • 16 GB DDR5MEMORY
  • 200 GB NVMeSTORAGE
  • Unmetered bandwidth
  • IPv4 & IPv6IPv6 is currently unavailable in France, Finland or the Netherlands. included
  • Free auto backupsIncludes one backup slot you can set to run daily, weekly or monthly.

Genoa VPS.G7

£119.97 Save  22 %
£93.73 Monthly
  • 8 vCPUAMD EPYC Genoa 4th generation 9xx4 with 3.25 GHz or similar, on Zen 4 architecture. AMD EPYC G4
  • 32 GB DDR5MEMORY
  • 250 GB NVMeSTORAGE
  • Unmetered bandwidth
  • IPv4 & IPv6IPv6 is currently unavailable in France, Finland or the Netherlands. included
  • Free auto backupsIncludes one backup slot you can set to run daily, weekly or monthly.

AMD Ryzen VPS.R1

£12.74 Save  18 %
£10.49 Monthly
  • 1 dedicated CPU AMD Ryzen 9 7950X with 4.5 GHz or similar, on Zen 4 architecture. vCPU
  • 4 GB DDR5MEMORY
  • 50 GB NVMeSTORAGE
  • Unmetered bandwidth
  • IPv4 & IPv6 included IPv6 support is currently unavailable in France, Finland or the Netherlands.
  • Auto backup included

AMD Ryzen VPS.R2

£22.49 Save  17 %
£18.74 Monthly
  • 2 dedicated CPUs AMD Ryzen 9 7950X with 4.5 GHz or similar, on Zen 4 architecture. vCPU
  • 8 GB DDR5MEMORY
  • 100 GB NVMeSTORAGE
  • Unmetered bandwidth
  • IPv4 & IPv6 included IPv6 support is currently unavailable in France, Finland or the Netherlands.
  • Auto backup included

AMD Ryzen VPS.R4

£82.48 Save  18 %
£67.48 Monthly
  • 8 dedicated CPUs AMD Ryzen 9 7950X with 4.5 GHz or similar, on Zen 4 architecture. vCPU
  • 32 GB DDR5MEMORY
  • 400 GB NVMeSTORAGE
  • Unmetered bandwidth
  • IPv4 & IPv6 included IPv6 support is currently unavailable in France, Finland or the Netherlands.
  • Auto backup included

*VAT excluded.

INCLUDED WITH EVERY PLAN

✓ No setup fees ✓1 Gbps network
✓ Full root access on KVM ✓ Free server monitoring ✓ Firewall management ✓24/7 support

SQL Server on Linux has no authentication mode to switch

SQL Server on Linux runs in mixed mode. Always. There's no mssql-conf key for authentication mode because there's no other mode to select, so any tutorial telling you to enable mixed mode on Ubuntu is copied from a Windows page. States 6 and 58 mean something else on Linux, usually a SID mismatch or an Active Directory integration that isn't working.

Resetting sa is a service-level operation. Stop the engine first:

sudo systemctl stop mssql-server
sudo /opt/mssql/bin/mssql-conf setup
sudo systemctl start mssql-server

That is the reset Microsoft's SQL Server on Linux troubleshooting guide gives. mssql-conf setup reprompts for the sa password as part of rerunning the whole configuration, edition included, so pick the edition the server already runs. The same guide still uses mssql-conf set-sa-password, but only inside its Rebuild system databases procedure, and the mssql-conf reference page no longer lists that subcommand. Both run with the service stopped.

State 11: Local administrators, UAC and explicit logins

This is the Windows case that eats an afternoon. A user is in the local Administrators group, that group is a sysadmin, so by every reasonable reading the login should work. It doesn't, because User Account Control strips the administrator token from the process unless it's elevated, and SQL Server sees the filtered token with no sysadmin membership on it. State 11 in the log, a confusing permission error in the client.

Two ways out. Launch SSMS with Run as administrator so the elevated token reaches the engine, which proves the diagnosis in about ten seconds. Then fix it properly. Add the account as an explicit login of its own, so nothing hangs on group membership:

CREATE LOGIN [CONTOSO\alice] FROM WINDOWS;
GO
ALTER SERVER ROLE sysadmin ADD MEMBER [CONTOSO\alice];
GO

Explicit logins survive UAC, group policy changes and someone tidying up the Administrators group six months from now.

Recover a server where sa is the only login you have

Lost sa on a Windows box with no other sysadmin? The instance has to come up in single-user mode so you can get in as a local administrator and rebuild access. Stop SQL Server Agent first, or Agent will grab the single connection before you do and lock you out of your own recovery.

net stop MSSQLSERVER
net start MSSQLSERVER /f /mSQLCMD
sqlcmd.exe -E -S localhost -Q "CREATE LOGIN [CONTOSO\alice] FROM WINDOWS; ALTER SERVER ROLE sysadmin ADD MEMBER [CONTOSO\alice];"
net stop MSSQLSERVER
net start MSSQLSERVER

The /mSQLCMD switch limits the one available connection to clients identifying themselves as sqlcmd, which stops a background service from taking the slot. Microsoft is blunt about the limits of that: "Don't use -m with an application name as a security feature. Client applications specify the application name through the connection string settings, so it can easily be spoofed with a false name." It's a convenience during recovery, nothing more.

Microsoft's article on connecting when system administrators are locked out also covers the Configuration Manager route, where you add -m to the startup parameters and restart. Either way, any member of the computer's local Administrators group can then connect as sysadmin. Physical and RDP access to a Windows Server SQL host therefore needs guarding as tightly as the sa password.

On Linux the equivalent is starting the binary by hand as the mssql user:

sudo systemctl stop mssql-server
sudo -u mssql /opt/mssql/bin/sqlservr -m"SQLCMD"

Leave that running in one terminal, connect from another, fix the login, then Ctrl+C and bring the service back with systemctl.

SQL error 26, error locating server/instance specified imitates an authentication failure more closely than anything else in the catalogue, so confirm the log has 18456 lines in it at all before going deep on state tables. Error 18456 is proof that the client reached the Database Engine and the engine answered. A connection that never gets that far produces a network-level message instead. No 18456 lines for the time of the outage means the network is where to look.

Questions?

What does login failed for user token-identified principal mean?

A Microsoft Entra identity authenticated, but the database you connected to has no user for it and the identity isn't the Entra admin. Microsoft's Azure database support team gives the fix in its post on this error: create a contained user with CREATE USER [[email protected]] FROM EXTERNAL PROVIDER; in that database. From SSMS, also set the database to connect to in the connection options, because the default target is master and the user often exists only in the application database.

Jörg L. Günther
About the author

Jörg L. Günther

Jörg has spent much of his career in enterprise software, working first with database deployments and customer environments, then in technical training and documentation. Since then he has written for companies working in virtualisation, database tooling and cloud infrastructure. The subjects he takes on often have a large operational component: database migrations, high-availability setups, storage configuration and procedures carried out on live systems. Jörg lives near Frankfurt. He plays piano and cycles for transport as much as for recreation. He's also been doing woodworking for several years - he says most of the furniture in his study is his own work.

Deploy your next project in seconds

Bring your winning ideas online faster, with modern hardware and unmetered bandwidth. Join a European cloud trusted by thousands of developers and businesses worldwide.